Файл: Пояснительная записка к курсовой работе Разработка по для кодового замка по курсу Программирование микропроцессоров.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 22.11.2023

Просмотров: 126

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

ЗАКЛЮЧЕНИЕ



В данной курсовой работе произведена разработка программного обеспечения для кодового замка на базе микроконтроллеров ESP8266 и ATMega328p. Также осуществлена разработка программного обеспечения для сервера, поддерживающего Java Virtual Machine.

Вся структура проекта и способ взаимодействия каждой из частей были придуманы мною и реализован в средах разработки ArduinoIDE, Microsoft Visual Code и IntelliJ Idea.

Устройство моего кодового замка очень просто и удобно в использовании для пользователя, а серверное программное обеспечение легко внедряется в уже готовое серверное окружение, что обеспечивает его дешевизну, и минимизацию затрат на внедрение этого устройства в корпоративной среде.

В ходе проектирования приобретен опыт работы и умение проектировать цифровые и микропроцессорные устройства, взаимодействующие сweb-сервисами, а также опыт разработки микросервисных серверных приложений.

Весь исходный код программного обеспечения расположен на сервисе GitHub по ссылке https://github.com/Niatomi/keylock.

СПИСОК ЛИТЕРАТУРЫ





  1. Общие сведения и характеристики Arduino. — Текст : электронный // Форум о разработке на Arduino : [сайт]. — 2022. — URL: http://arduino.ru/ (дата обращения: 25.05.2022).

  2. Общие сведения и характеристики NodeMCU. — Текст : электронный // Российское ардуино-сообщество : [сайт]. — 2022. — URL: https://arduinomaster.ru/ (дата обращения: 25.05.2022).

  3. Описание и характеристики LCD 2004 дисплея. — Текст : электронный // Проекты на ардуино : [сайт]. — 2022. — URL: http://arduino-project.net/ (дата обращения: 25.05.2022).

  4. Описание и характеристики пьезоэлемента. — Текст : электронный // Автоблог : [сайт]. — 2022. — URL: https://shamrin.ru/datchik-zummer-chto-eto/ (дата обращения: 25.05.2022).

  5. Описание и характеристики линейного датчика Холла KY-024. — Текст : электронный // Сайт магазина DUINO : [сайт]. — 2022. — URL: https://duino.ru/datchik-kholla-ky-024 (дата обращения: 25.05.2022).

  6. Описание и характеристики Сервоприводы Ардуино SG90. — Текст : электронный // Российское ардуино-сообщество : [сайт]. — 2022. — URL: https://arduinomaster.ru/motor-dvigatel-privod/servoprivody-arduino-sg90-mg995-shema-podklyuchenie-upravlenie/ (дата обращения: 25.05.2022).

  7. Библиотека для отладки на AVR устройствах. — Текст : электронный // Веб-сервис для хостинга IT-проектов и их совместной разработки GitHub : [сайт]. — 2022. — URL: https://github.com/jdolinay/avr_debug (дата обращения: 25.05.2022).

  8. Формализованная спецификация и экосистема множества инструментов, предоставляющая интерфейс между front-end системами. — Текст : электронный // The OpenAPI Initiative (OAI) : [сайт]. — 2022. — URL: https://www.openapis.org/ (дата обращения: 25.05.2022).

  9. Документация к сURL. — Текст : электронный // сURL : [сайт]. — 2022. — URL: https://curl.se/ (дата обращения: 25.05.2022).

  10. Документация по работе с Postman. — Текст : электронный // Postman API platform for building and using APIs : [сайт]. — 2022. — URL: https://www.postman.com/ (дата обращения: 25.05.2022).

  11. Building a REST API with Spring. — Текст : электронный // Baeldung : [сайт]. — 2022. — URL: https://www.baeldung.com/ (дата обращения: 25.05.2022).

  12. Spring MVC. — Текст : электронный // Baeldung : [сайт]. — 2022. — URL: https://www.baeldung.com/spring-mvc-tutorial (дата обращения: 25.05.2022).

  13. The DTO Pattern (Data Transfer Object). — Текст : электронный // Baeldung : [сайт]. — 2022. — URL: https://www.baeldung.com/java-dto-pattern (дата обращения: 25.05.2022).

  14. ResponseEntity (Spring Framework 5.3.20 API). — Текст : электронный // Baeldung : [сайт]. — 2022. — URL: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/ResponseEntity.html (дата обращения: 25.05.2022).

  15. CrudRepository, JpaRepository, and PagingAndSortingRepository in Spring Data. — Текст : электронный // Baeldung : [сайт]. — 2022. — URL: https://www.baeldung.com/spring-data-repositories (дата обращения: 25.05.2022).



ПРИЛОЖЕНИЕ 1
Схема электрическая принципиальная



ПРИЛОЖЕНИЕ 2
Спецификация






ПРИЛОЖЕНИЕ 3
Исходное ПО аппаратного уровня


#include

#include

#define GREEN A0

#define RED A1

#define ZOOMER 10

#define HALL 2

#define SS_PIN A2

#define RST_PIN A3

// Keypad init

const byte ROWS = 3;

const byte COLS = 4;

charhexaKeys[ROWS][COLS] = {

{'1','2','3','A'},

{'4','5','6','0'},

{'7','8','9','C'}

};

byterowPins[ROWS] = {5, 4, 3};

bytecolPins[COLS] = {9, 8, 7, 6};

Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

// LCD init

LiquidCrystal_I2C lcd (0x27, 20, 4);

byteupsideDownDegree[8]= {

B00000,

B00000,

B00000,

B00000,

B00000,

B10001,

B01010,

B00100,

};

bytefilledSpace[8]= {

B11111,

B11111,

B11111,

B11111,

B11111,

B11111,

B11111,

B11111,

};

byteunFilledSpace[8]= {

B11111,

B10001,

B10001,

B10001,

B10001,

B10001,

B10001,

B11111,

};

booleanshowPassword = true;

boolean sound = false;

booleanisLocked = false;

volatile unsigned long globalTimeBufferMillis = 0;

byteincorrectCount = 0;

void setup(){

Serial.begin(9600);

Serial.setTimeout(100);

lcd.init();

lcd.backlight();

lcd.createChar(1,upsideDownDegree);

lcd.createChar(2,filledSpace);

lcd.createChar(3,unFilledSpace);

pinMode(GREEN, OUTPUT);

pinMode(RED, OUTPUT);

doorIsOpened();

attachInterrupt(0, doorInteruptAction, FALLING);

}

booleanisAccessFromPassword = false;

voiddoorInteruptAction() {

detachInterrupt(0);

incorrectCount = 6;

if (!isAccessFromPassword) Serial.write("hall:UnauthorizedAccess@");

Serial.flush();

}

void loop() {

attachInterrupt(0, doorInteruptAction, FALLING);

openMenu();

}

voiddoorIsOpened() {

if (digitalRead(HALL)) {

digitalWrite(GREEN, 0);

digitalWrite(RED, 1);

// return false;

} else {

digitalWrite(GREEN, 1);

digitalWrite(RED, 0);

// return true;

}

}

voidopenMenu() {

getConfig();

if (!(incorrectCount>= 3) && !isLocked) {

drawMenu();

listenKeyboardAndChanegeLcd();

} else {

if (isLocked == false)

incorrectCount = 0;

drawBlock();

}

}

voiddrawBlock() {

lcd.clear();

getConfig();

lcd.setCursor(0, 0);

lcd.print("Access blocked");

improvedDelay(5000);

}

voiddrawMenuHeader() {

lcd.setCursor(0, 0);

lcd.print("Choose action");

lcd.setCursor(0, 1);

for (inti = 0; i< 20; i++) {

lcd.print("-");

}

lcd.setCursor(0, 2);

lcd.print("^");

lcd.setCursor(0, 3);

lcd.write(1);

}

voiddrawMenu() {

drawMenuHeader();

keyAndSettingsScene();

lcd.setCursor(1, 2);

lcd.blink_on();

}

voidkeyAndSettingsScene() {

lcd.clear();

drawMenuHeader();

lcd.setCursor(2, 2);

lcd.print("Keyboard");

lcd.setCursor(2, 3);

lcd.print("Settings");

}

booleanisPriorized = false;

voidgetConfig() {

Serial.flush();

Serial.write("getConfig");

Serial.flush();

longawaitTime = 1000;

longenterWithTime = millis();

while (true) {

if (Serial.available()) {

String expression = Serial.readStringUntil('-');

expression = expression.substring(expression.indexOf(':') + 1, expression.length());

String config = "1";

if (!isPriorized&&expression.charAt(0) == '1') {

sound = true;

} else if (!isPriorized&&expression.charAt(0) == '0') {

sound = false;

}

if (!isPriorized&&expression.charAt(1) == '1') {

showPassword = true;

} else if (!isPriorized&&expression.charAt(1) == '0') {

showPassword = false;

}

if (expression.charAt(2) == '1') {

isLocked = true;

} else {

isLocked = false;

}

Serial.flush();

return;

} else if (millis() - enterWithTime>awaitTime) {

incorrectCount = 0;

drawUpLimitAwaitTime();

return;

}

}

Serial.flush();

}

voidlistenKeyboardAndChanegeLcd() {

byte type = 2;

while (true) {

charcustomKey = customKeypad.getKey();

if (customKey) {

getConfig();

if (sound) tone(ZOOMER, 220, 50);

if (customKey == '2') {

if (type == 2) {

type = 3;

drawScene(type, false);

} else if (type == 3) {

type--;

drawScene(type, true);

} else {

type--;

drawScene(type, false);

}

} else if (customKey == '5') {

if (type == 2) {

openUsingKeypad();

return;

} else if (type == 3) {

openSettings();

return;

} else if (type == 4) {

openSettings();

return;

}

} else if (customKey == '8') {

if (type == 3) {

type = 2;

} else {

type++;

}

drawScene(type, false);

}

}

}

}

voidopenSettings() {

drawMenuSettings();

listenKeyboardOnSettings();

}

voiddrawMenuSettings() {

lcd.clear();

lcd.setCursor(0, 0);

lcd.print("Settings");

lcd.setCursor(0, 1);

if (showPassword) lcd.write(2);

if (!showPassword) lcd.write(3);

lcd.setCursor(2, 1);

lcd.print("Show password");

lcd.setCursor(0, 2);

if (sound) lcd.write(2);

if (!sound) lcd.write(3);

lcd.setCursor(2, 2);

lcd.print("Sound");

lcd.setCursor(1, 1);

}

voidlistenKeyboardOnSettings() {

bytetypeSetting = 1;

while (true) {

charcustomKey = customKeypad.getKey();

if (customKey) {

if (customKey == '2') {

if (typeSetting == 1) {

typeSetting = 2;

} else {

typeSetting--;

}

lcd.setCursor(1, typeSetting);

} else if (customKey == '5') {

isPriorized = true;

if (typeSetting == 1) {

showPassword = !showPassword;

printSuccesSettingsUpdate();

return;

} else if (typeSetting == 2) {

sound = !sound;

printSuccesSettingsUpdate();

return;

}

} else if (customKey == '8') {

if (typeSetting == 2) {

typeSetting = 1;

} else {

typeSetting++;

}

lcd.setCursor(1, typeSetting);

} else if (customKey == 'C') {

return;

}

}

}

}

voidprintSuccesSettingsUpdate() {

lcd.clear();

lcd.setCursor(0, 0);

lcd.print("Settings updated");

improvedDelay(1000);

}

voiddrawScene(byte type, booleanisPrevious) {

if (type == 2) {

keyAndSettingsScene();

lcd.setCursor(1, type);

}

if (type == 3) {

keyAndSettingsScene();

lcd.setCursor(1, type);

}

}

String pass = "";

String key = "";

String enteringPassword = "";

voidopenUsingKeypad() {

lcd.clear();

drawCodeHeader();

while (true) {

charcustomKey = customKeypad.getKey();

if (customKey) {

if (sound) tone(ZOOMER, 220, 50);

if (customKey == 'A') {

lcd.clear();

lcd.setCursor(0, 0);

lcd.print("Password check");

break;

} else if (customKey == 'C') {

enteringPassword = enteringPassword.substring(0, enteringPassword.length() - 1);

drawPassword();

} else {

enteringPassword += customKey;

drawPassword();

}

}

}

applyPassword(!isLocked&&sendPasswordOnCheck(enteringPassword, "keypad"));

enteringPassword = "";

}

charconstPassword[71];

booleansendPasswordOnCheck(String enteringPassword, String type) {

Serial.flush();

for (inti = 0; i
constPassword[i] = '-';

}

String sendingData = "check:" + type + ":" + enteringPassword;

for (inti = 0; i
constPassword[i] = sendingData.charAt(i);

}

Serial.write(constPassword);

Serial.flush();

improvedDelay(2000);

longawaitTime = 10000;

longenterWithTime = millis();

while (true) {

if (Serial.available()) {

String isRight;

isRight = Serial.readStringUntil('*');

Serial.println();

Serial.println(isRight);

if (isRight.indexOf("open") != -1) {

Serial.flush();

return true;

} else if (isRight.indexOf("wrong") != -1) {

Serial.flush();

return false;

}

}

if (millis() - enterWithTime>awaitTime) {

incorrectCount = 0;

drawUpLimitAwaitTime();

return false;

}

}

}

voiddrawUpLimitAwaitTime() {

lcd.clear();

lcd.setCursor(0, 0);

lcd.print("Uptime server limit");

improvedDelay(1000);

lcd.clear();

}

voidapplyPassword(booleanpasswordIsRight) {

if (passwordIsRight) {

isAccessFromPassword = true;

confirmed();

detachInterrupt(0);

improvedDelay(10000);

checkDoor();

attachInterrupt(0, doorInteruptAction, FALLING);

isAccessFromPassword = false;

} else {

denied();

incorrectCount++;

if (incorrectCount == 3) {

isLocked = true;

sendBlockState();

}

}

}

booleancheckDoor() {

if (!digitalRead(HALL)) {

Serial.flush();

Serial.write("hall:unClosed@");

Serial.flush();

} else {

Serial.flush();

Serial.write("hall:Closed@");

Serial.flush();

}

Serial.flush();

doorIsOpened();

}

voidsendBlockState() {

Serial.flush();

Serial.write("lock");

Serial.flush();

}

voiddrawCodeHeader() {

lcd.setCursor(0, 0);

lcd.print("Enter your password:");

lcd.setCursor(0, 1);

}

voiddrawPassword() {

lcd.clear();

drawCodeHeader();

lcd.setCursor(0, 1);

if (showPassword) {

lcd.print(enteringPassword);

} else {

for (inti = 0; i
lcd.print("*");

}

}

}

void confirmed() {

drawConfirm();

openLock();

if (sound) confirmSound();

}

voiddrawConfirm() {

lcd.clear();

lcd.setCursor(0, 0);

lcd.print("Password confirmed");

}

voidopenLock() {

digitalWrite(GREEN, 1);

digitalWrite(RED, 0);

}

voidconfirmSound() {

tone(ZOOMER, 220, 100);

improvedDelay(200);

noTone(ZOOMER);

tone(ZOOMER, 220, 100);

improvedDelay(200);

noTone(ZOOMER);

tone(ZOOMER, 220, 100);

}

void denied() {

drawIncorrectPassword();

deniedSound();

improvedDelay(500);

}

voiddrawIncorrectPassword() {

digitalWrite(GREEN, 0);

digitalWrite(RED, 1);

lcd.clear();

lcd.setCursor(0, 0);

lcd.print("Password denied");

}

voiddeniedSound() {

tone(ZOOMER, 320, 100);

improvedDelay(200);

noTone(ZOOMER);

tone(ZOOMER, 320, 100);

improvedDelay(200);

noTone(ZOOMER);

tone(ZOOMER, 320, 100);

}

voidimprovedDelay(unsigned intwaitTime) {

globalTimeBufferMillis = millis();

booleancooldownState = true;

while (cooldownState) {

if (millis() - globalTimeBufferMillis>waitTime)

cooldownState = false;

}

}
1   2   3   4   5   6   7   8   9   10

ПРИЛОЖЕНИЕ 4
Исходное ПО сетевого уровня


#include

#include

#include

#include

#include

#include

#define HTTP 5

#define HARDWARE_INDICATION 4

#define LED_BUILTIN 2

volatile unsigned long globalTimeBufferMillis = 0;

// WiFi, HTTP

// const char* ssid = "Ttk 139";

// const char* password = "631790355";

const char* ssid = "Niatomi";

const char* password = "1234567890";

WiFiClient client;

IPAddresslocal(192, 168, 137, 1);

uint16_t port = 8080;

DynamicJsonDocumentdoc(2048);

unsigned long openerId;

String enteringPassword = "";

void setup() {

WiFi.begin(ssid, password);

pinMode(HTTP, OUTPUT);

pinMode(HARDWARE_INDICATION, OUTPUT);

digitalWrite(HTTP, LOW);

digitalWrite(HARDWARE_INDICATION, LOW);

while (WiFi.status() != WL_CONNECTED)

delay(500);

Serial.begin(9600);

Serial.setTimeout(5);

}

voidgetPasswords() {

if (client.connect(local, port)) {

digitalWrite(HTTP, HIGH);

// Send HTTP request

client.println("GET /esp HTTP/1.0\r\n");

client.println("Host: " + local.toString() + ":8080");

// Skip HTTP headers

charendOfHeaders[] = "\r\n\r\n";

if (!client.find(endOfHeaders)) {

// Serial.println("Invalid response");

return;

}

deserializeJson(doc, client);

client.stop();

digitalWrite(HTTP, LOW);

}

}

booleancheckPassword(String enteringPassword, String enteringType) {

getPasswords();

for (JsonObject item : doc.as()) {

openerId = item["openerId"];

String type = item["type"];

String value = item["value"];

if (type == enteringType) {

if (value == enteringPassword) {

return true;

}

}

}

openerId = 1;

return false;

}

void loop() {

hardwareListener();

}

voidhardwareListener() {

if (Serial.available()) {

String expression = Serial.readStringUntil('-');

String method = expression.substring(0, expression.indexOf(':'));

expression = expression.substring(expression.indexOf(':') + 1, expression.length());

if (method == "check") {

String type = expression.substring(0, expression.indexOf(':'));

expression = expression.substring(expression.indexOf(':') + 1, expression.length());

enteringPassword = expression.substring(0, expression.length());

if (type == "keypad") {

if (checkPassword(enteringPassword, type)) {

digitalWrite(HARDWARE_INDICATION, HIGH);

Serial.flush();

Serial.write("open*");

Serial.flush();

sendAction("Open");

digitalWrite(HARDWARE_INDICATION, LOW);

} else {

digitalWrite(HARDWARE_INDICATION, HIGH);

Serial.flush();

Serial.write("wrong*");

Serial.flush();

sendAction("WrongKeyAccess");

digitalWrite(HARDWARE_INDICATION, LOW);

}

}

}

if (method == "hall") {

openerId = 1;

expression = expression.substring(0, expression.indexOf('@'));

sendAction(expression);

}

if (method == "getConfig") {

getServerConfig();

}

if (method.indexOf("lock") != -1) {

sendLockConfigAction();

}

if (method.indexOf("config") != -1) {

sendSettingsConfigAction();

}

if (method == "getConfig") {

getServerConfig();

}

Serial.flush();

}

}

voidsendSettingsConfigAction() {

digitalWrite(HTTP, HIGH);

if (client.connect(local, port)) {

client.println("POST /esp/setConfig HTTP/1.1");

client.println("Host: " + local.toString() + ":8080");

client.println();

improvedDelay(200);

client.stop();

}

digitalWrite(HTTP, LOW);

}

voidsendLockConfigAction() {

digitalWrite(HTTP, HIGH);

if (client.connect(local, port)) {

client.println("POST /esp/setLock HTTP/1.1");

client.println("Host: " + local.toString() + ":8080");

client.println();

improvedDelay(200);

client.stop();

}

digitalWrite(HTTP, LOW);

}

booleanre_read_password;

charsendingConfig[12];

voidgetServerConfig() {

String arduinoConfiguration = "config:";

DynamicJsonDocumentconfig(128);

if (client.connect(local, port)) {

digitalWrite(HTTP, HIGH);

// Send HTTP request

client.println("GET /esp/getConfig HTTP/1.0\r\n");

client.println("Host: " + local.toString() + ":8080");

// Skip HTTP headers

charendOfHeaders[] = "\r\n\r\n";

if (!client.find(endOfHeaders)) {

// Serial.println("Invalid response");

return;

}

deserializeJson(config, client);

client.stop();

digitalWrite(HTTP, LOW);

}

boolean sound = config["sound"].as();

booleanshowPassword = config["showPassword"].as();

re_read_password = config["re_read_password"].as();

boolean lock = config["lock"].as();

arduinoConfiguration.concat(sound);

arduinoConfiguration.concat(showPassword);

arduinoConfiguration.concat(lock);

arduinoConfiguration.concat("-");

for (inti = 0; i
sendingConfig[i] = arduinoConfiguration.charAt(i);

}

digitalWrite(HARDWARE_INDICATION, HIGH);

Serial.write(sendingConfig);

Serial.flush();

digitalWrite(HARDWARE_INDICATION, LOW);

}

voidsendAction(String action) {

if (client.connect(local, port)) {

digitalWrite(HTTP, HIGH);

StaticJsonDocument<250>docOut;

docOut["openerId"] = openerId;

docOut["description"] = action;

// Write response headers

client.println("POST /esp HTTP/1.1");

client.println("Host: " + local.toString() + ":8080");

client.println("Content-Type: application/json");

client.println("Connection: close");

client.print("Content-Length: ");

client.println(measureJsonPretty(docOut));

client.println();

serializeJsonPretty(docOut, client);

client.stop();

digitalWrite(HTTP, LOW);

}

}

voidsendHttpAction() {

StaticJsonDocument<48>docOut;

}

voidimprovedDelay(unsigned intwaitTime) {

globalTimeBufferMillis = millis();

booleancooldownState = true;

while (cooldownState) {

if (millis() - globalTimeBufferMillis>waitTime)

cooldownState = false;

}

}

ПРИЛОЖЕНИЕ 5
Антиплагиат


48>250>
1   2   3   4   5   6   7   8   9   10