/* Copyright (C) 2024 Riccardo Henning and Philipp Wagner This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include // NFC-Pin-Definitionen und -Objekt #define PN532_SCK (91) #define PN532_MOSI (90) #define PN532_SS (4) #define PN532_MISO (89) Adafruit_PN532 nfc(PN532_SCK, PN532_MISO, PN532_MOSI, PN532_SS); //NFC-Request für Anlernen bool request1 = false; USBHostMSD msd; mbed::FATFileSystem usb("usb"); mbed::DigitalOut otg(PB_8, 1); const int pinRedLED = 86; // Rot const int pinGreenLED = 87; // Grün const int pinBlueLED = 88; // Blau const int pinStatusRedLED = 26; // ROT externe LED const int pinStatusGreenLED = 24; // Grün externe LED const int pinStatusYellowLED = 22; // Gelb externe LED //ISR bool doorIsOpened = false; volatile bool ButtonPressed = false; volatile unsigned long lastPressTime = 0; // WiFI WiFiServer server(80); // Keypad Initialisierung const byte ROWS = 4; //vier Reihen const byte COLS = 4; //vier Spalten char hexaKeys[ROWS][COLS] = { { '1', '2', '3', 'A' }, { '4', '5', '6', 'B' }, { '7', '8', '9', 'C' }, { '*', '0', '#', 'D' } }; byte rowPins[ROWS] = { 32, 34, 36, 38 }; //verbinde mit den Reihen-Pinouts des Keypads byte colPins[COLS] = { 40, 42, 44, 46 }; //verbinde mit den Spalten-Pinouts des Keypads //LCD Initialisierung const int rs = 49, en = 51, d4 = 33, d5 = 35, d6 = 37, d7 = 39; LiquidCrystal lcd(rs, en, d4, d5, d6, d7); Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); //Überprüfung String inputString = ""; // Zum Speichern der Tasteneingaben String correctString = ""; // Der zu überprüfende String //Ultraschall int echo_pin = 7; int trig_pin = 6; bool isPackageSpace = true; bool isPackageInside = false; long distanceUltraSonic = 0; void setup() { attachInterrupt(digitalPinToInterrupt(71), isrPin71, CHANGE); Serial.begin(9600); // Ultraschall Set pinMode(trig_pin, OUTPUT); pinMode(echo_pin, INPUT); // LCD Beginnen analogWrite(2, 50); // Kontrast LCD einstellen lcd.begin(16, 2); // LCD Startup Message und Copyright lcd.print("Startup Brain V4"); lcd.setCursor(0, 1); lcd.print("c:Wagner|Henning"); // EXTERNE STATUS LEDs pinMode(pinStatusRedLED, OUTPUT); pinMode(pinStatusGreenLED, OUTPUT); pinMode(pinStatusYellowLED, OUTPUT); digitalWrite(pinStatusRedLED, HIGH); digitalWrite(pinStatusGreenLED, HIGH); digitalWrite(pinStatusYellowLED, HIGH); // NFC-Kram nfc.begin(); uint32_t versiondata = nfc.getFirmwareVersion(); while (!versiondata) { ledBlink(GPIOJ, 14); lcd.clear(); lcd.println("Error starting: "); lcd.setCursor(0, 1); lcd.println("NFC Module error"); delay(500); } nfc.setPassiveActivationRetries(0x00); //NFC-Anlern-Knopf --> BOOT0 auf Giga R1 Wifi pinMode(PC_13, INPUT); //USB-A pinMode(PA_15, OUTPUT); digitalWrite(PA_15, HIGH); // Kommunikationsleitungsen pinMode(69, OUTPUT); pinMode(71, INPUT); int randomSeedValue = analogRead(0); // RandomSeed value with some Noise... randomSeed(randomSeedValue); while (!msd.connect()) { delay(1000); } int err = usb.mount(&msd); if (err) { Serial.println("Error mounting USB device"); while (1) ; } Serial.println("Mounting USB device... done"); //Onboard LED pinMode(pinRedLED, OUTPUT); pinMode(pinGreenLED, OUTPUT); pinMode(pinBlueLED, OUTPUT); digitalWrite(pinRedLED, LOW); char ssid[32] = ""; char pass[32] = ""; FILE *wifiFile = fopen("/usb/WiFi.txt", "r"); if (wifiFile) { fscanf(wifiFile, "%31s\n%31s", ssid, pass); fclose(wifiFile); } else { strcpy(ssid, "SSID"); strcpy(pass, "PASSWORD"); FILE *newWifiFile = fopen("/usb/WiFi.txt", "w"); if (newWifiFile) { fprintf(newWifiFile, "%s\n%s", ssid, pass); fclose(newWifiFile); } } int status = WL_IDLE_STATUS; while (status != WL_CONNECTED) { status = WiFi.begin(ssid, pass); delay(10000); } server.begin(); digitalWrite(pinGreenLED, LOW); digitalWrite(pinRedLED, HIGH); digitalWrite(pinBlueLED, HIGH); //externer LED-Status statusYellow(); // Serielle Ausgabe der IP Serial.println("Connected Succesfully!"); IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); // LCD Start des Programmes lcd.clear(); lcd.print("IP: "); lcd.setCursor(0, 1); lcd.print(ip); delay(5000); // Warte 5 Sekunden lcdWritePinInterface(); } void loop() { // NFC-Anlern-Knopp if (digitalRead(PC_13) == HIGH) { Serial.println("Anlernen angefragt."); lcd.clear(); lcd.print("neuen NFC-TAG"); lcd.setCursor(0, 1); lcd.print("vorzeigen"); request1 = true; // Setzen Sie request1 auf true, wenn der Button gedrückt wurde } // NFC-Tag lesen uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; uint8_t uidLength; boolean success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength); if (success) { // UID in eine String-Repräsentation umwandeln String uidString = ""; for (uint8_t i = 0; i < uidLength; i++) { uidString += String(uid[i], HEX); } // Überprüfen, ob der Button gedrückt wurde if (request1) { // UID in die Datei "NFC-UIDS.txt" schreiben FILE *file = fopen("/usb/NFC-UIDS.txt", "a+"); if (file) { fprintf(file, "%s\n", uidString.c_str()); fclose(file); // LCD-Anzeige aktualisieren lcd.clear(); lcd.print("NFC-Tag"); lcd.setCursor(0, 1); lcd.print("gespeichert!"); delay(1000); lcdWritePinInterface(); request1 = false; } } else { // UID in der Datei "NFC-UIDS.txt" überprüfen FILE *file = fopen("/usb/NFC-UIDS.txt", "r"); boolean tagFound = false; // Variable hinzufügen, um zu überwachen, ob der Tag gefunden wurde if (file) { char line[32]; while (fgets(line, sizeof(line), file)) { String lineString = String(line); lineString.trim(); if (lineString.equalsIgnoreCase(uidString)) { // Verwende equalsIgnoreCase für eine nicht case-sensitive Überprüfung Serial.println("NFC: Akzeptiert"); //LED-Status statusGreen(); lcd.clear(); lcd.print("NFC-TAG:"); lcd.setCursor(0, 1); lcd.print("akzeptiert!"); delay(2000); lcdWritePinInterface(); //LED-Status statusYellow(); tagFound = true; // Tag gefunden // Kommunikations-UPDATE openDoor(); break; } } fclose(file); if (!tagFound) { Serial.println("NFC: Nicht akzeptiert"); // Wenn der Tag nicht gefunden wurde, zeige diese Nachricht lcd.clear(); statusRed(); lcd.print("NFC-TAG:"); lcd.setCursor(0, 1); lcd.print("nicht akzeptiert!"); delay(1000); lcdWritePinInterface(); statusYellow(); } } } } WiFiClient client = server.available(); if (client) { //Serial.println("Client start"); lcd.clear(); lcd.print("Webinterface!"); lcd.setCursor(0, 1); lcd.print("keine Eingabe..."); boolean currentLineIsBlank = true; String request = ""; while (client.connected()) { if (client.available()) { //Serial.println(request); char c = client.read(); if (c == '\n' && currentLineIsBlank) { if (request.indexOf("/generie}rePIN ") != -1) { String pin = generatePIN(); // Schreibe die generierte PIN direkt in die Datei PINs.txt auf dem USB-Stick FILE *pinFile = fopen("/usb/PINs.txt", "a+"); if (pinFile) { fprintf(pinFile, "%s\n", pin.c_str()); fclose(pinFile); } client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); client.println(); client.println(""); client.println(""); client.println("Deine generierte PIN: " + pin); client.println(""); } else if (request.indexOf("/ ") != -1) { // Senden Sie eine HTML-Seite zurück, die den Status dedistanceUltraSonic = r Tür anzeigt client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); client.println("Refresh: 5"); client.println(); client.println(""); client.println(""); client.println("Packstation"); client.println("

Packstation (Selbstbau)

"); client.println("

Codename: Brain (Version: 4)

"); client.println("

Tuerstatus:

"); if (doorIsOpened) { client.println("

Die Tuer ist geoeffnet.

"); } else { client.println("

Die Tuer ist geschlossen.

"); } client.println("

Packetstatus

"); if (isPackageInside) { client.println("

In der Packstation liegen Packete

"); } else { client.println("

Kein Packet ist in der Packstation

"); } client.println("

Code-Generierung:

"); client.println(" Zusteller-PIN generieren "); client.println("
"); client.println(" Besitzer-PIN generieren "); client.println(""); } else if (request.indexOf("/generieOWNERPIN ") != -1) { String pin = generateOwnerPIN(); FILE *pinFile = fopen("/usb/OWNER-PINs.txt", "a+"); if (pinFile) { fprintf(pinFile, "%s\n", pin.c_str()); fclose(pinFile); } client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); client.println(); client.println(""); client.println(""); client.println("Deine generierte PIN: " + pin); client.println(""); } else { client.println("HTTP/1.1 404 Not found"); client.println("Content-Type: text/html"); client.println("Connection: close"); client.println(); client.println(""); client.println(""); client.println("404 Not Found"); client.println(""); } break; } if (c == '\n') { currentLineIsBlank = true; } else if (c != '\r') { currentLineIsBlank = false; } request += c; } } client.stop(); delay(100); lcdWritePinInterface(); //Serial.println("Client Stop"); } //Serial.println("Keypad 1"); char customKey = customKeypad.getKey(); //Serial.println("Keypad 2"); if (customKey) { if (customKey == '#') { // Überprüfe, ob die eingegebene PIN in den korrekten PINs enthalten ist bool pinAccepted = false; FILE *pinFile = fopen("/usb/PINs.txt", "r"); if (pinFile) { char line[32]; while (fgets(line, sizeof(line), pinFile)) { String correctPin = String(line); correctPin.trim(); if (inputString == correctPin) { if (isPackageSpace) { // Überprüfung ob denn noch genung Platz drinne ist.. pinAccepted = true; break; // Beende die Schleife, wenn eine korrekte PIN gefunden wurde } } } fclose(pinFile); } if (!pinAccepted) { // Überprüfe, ob die eingegebene PIN in den OWNER-PINs enthalten ist pinFile = fopen("/usb/OWNER-PINs.txt", "r"); if (pinFile) { char line[32]; while (fgets(line, sizeof(line), pinFile)) { String correctPin = String(line); correctPin.trim(); if (inputString == correctPin) { pinAccepted = true; break; // Beende die Schleife, wenn eine korrekte PIN gefunden wurde } } fclose(pinFile); } } if (pinAccepted) { //LED-Status Serial.println("PIN: akzeptiert"); lcd.clear(); lcd.print("PIN:"); lcd.setCursor(0, 1); lcd.print("akzeptiert!"); delay(1000); lcdWritePinInterface(); // Kommunikations-UPDATE openDoor(); // Lösche die verwendete PIN aus der Datei PINs.txt FILE *pinFile = fopen("/usb/PINs.txt", "r"); FILE *tempFile = fopen("/usb/temp.txt", "w"); if (pinFile && tempFile) { char line[32]; while (fgets(line, sizeof(line), pinFile)) { String currentPin = String(line); currentPin.trim(); // Schreibe alle PINs außer der verwendeten PIN in die temporäre Datei if (currentPin != inputString) { fprintf(tempFile, "%s\n", currentPin.c_str()); } } fclose(pinFile); fclose(tempFile); // Lösche die ursprüngliche Datei und benenne die temporäre Datei um remove("/usb/PINs.txt"); rename("/usb/temp.txt", "/usb/PINs.txt"); } inputString = ""; // Setze den Eingabestring zurück } else { lcd.clear(); statusRed(); Serial.println("PIN: nicht akzeptiert!"); lcd.print("PIN:"); lcd.setCursor(0, 1); lcd.print("nicht akzeptiert!"); delay(1000); lcdWritePinInterface(); statusYellow(); } inputString = ""; // Setze den Eingabestring zurück statusYellow(); } else if (customKey == '*') { // Setze den Eingabestring zurück inputString = ""; lcd.clear(); lcd.print("Eingabe"); lcd.setCursor(0, 1); lcd.print("zurueckgesetzt"); delay(1000); lcdWritePinInterface(); } else { // Füge die gedrückte Taste zum Eingabestring hinzu inputString += customKey; lcd.print(customKey); } } if (doorIsOpened) { //andere LEDs aus. digitalWrite2(GPIOJ, 12, false); digitalWrite2(GPIOG, 12, false); digitalWrite2(GPIOJ, 14, false); lcd.clear(); lcd.print("Tuer offen!"); ledBlink(GPIOG, 12); // PIN 24 lcdWritePinInterface(); //Ausgangszustand digitalWrite2(GPIOJ, 12, true); digitalWrite2(GPIOG, 12, false); digitalWrite2(GPIOJ, 14, false); } ultraSonicDistanceRead(); delay(1); } String generatePIN() { const char validCharacters[] = "ABCD0123456789"; String pin = ""; for (int i = 0; i < 6; i++) { int index = random(0, sizeof(validCharacters) - 1); pin += validCharacters[index]; } return pin; } String generateOwnerPIN() { const char validCharacters[] = "ABCD0123456789"; String pin = ""; for (int i = 0; i < 7; i++) { int index = random(0, sizeof(validCharacters) - 1); pin += validCharacters[index]; } return pin; } void isrPin71() { static unsigned long lastPressTime = 0; // Nur den Druck verarbeiten, wenn seit dem letzten Druck mehr als 20 Millisekunden vergangen sind if (millis() - lastPressTime >= 20) { if (digitalRead(71) == 0) { doorIsOpened = false; } if (digitalRead(71) == 1) { doorIsOpened = true; } ButtonPressed = true; lastPressTime = millis(); } } // UND JETZT, NACH 500 Stunden: ASSEMBLY!!!!!! void ledBlink(GPIO_TypeDef *port, uint32_t pin) { digitalWrite2(port, pin, true); delayApproxOneSecond(); digitalWrite2(port, pin, false); delayApproxOneSecond(); } void digitalWrite2(GPIO_TypeDef *port, uint32_t pin, bool state) { volatile uint32_t *bsrr = &(port->BSRR); if (state) { // Setzt den Pin asm volatile( "mov r0, %0\n\t" // Lade die Adresse des BSRR-Registers "mov r1, #1\n\t" // Setze r1 auf 1 "lsl r1, r1, %1\n\t" // Verschiebe 1 um die Anzahl der Bits, die durch pin angegeben sind "str r1, [r0]\n\t" // Schreibe den Wert in BSRR, setzt den Pin : // Keine Ausgaben : "r"(bsrr), "r"(pin) : "r0", "r1" // Verwendete Register ); } else { // Löscht den Pin asm volatile( "mov r0, %0\n\t" // Lade die Adresse des BSRR-Registers "mov r1, #1\n\t" // Setze r1 auf 1 "lsl r1, r1, %1\n\t" // Verschiebe 1 um pin + 16 Positionen "str r1, [r0]\n\t" // Schreibe den Wert in BSRR, löscht den Pin : // Keine Ausgaben : "r"(bsrr), "r"(pin + 16) : "r0", "r1" // Verwendete Register ); } } void delayApproxOneSecond() { asm volatile( "mov r0, %0 \n" // Lädt den Wert (480000000) in das Register r0 "1: \n" // Beginn des Schleifenlabels "subs r0, #1 \n" // Subtrahiert 1 von r0 und aktualisiert die Flags "bne 1b \n" // Springt zurück zum Label 1, wenn r0 nicht 0 ist : // keine Ausgaben : "r"(480000000) // Der Wert, der in r0 geladen wird : "r0" // Teilt dem Compiler mit, dass r0 verändert wird ); } //ENDE ASSEMBLY void lcdWritePinInterface() { lcd.clear(); lcd.print("PIN eingeben:"); lcd.setCursor(0, 1); } void openDoor() { digitalWrite(69, HIGH); delay(100); digitalWrite(69, LOW); } void statusGreen() { digitalWrite(pinStatusGreenLED, HIGH); digitalWrite(pinStatusRedLED, LOW); digitalWrite(pinStatusYellowLED, LOW); } void statusYellow() { digitalWrite(pinStatusRedLED, LOW); digitalWrite(pinStatusGreenLED, LOW); digitalWrite(pinStatusYellowLED, HIGH); } void statusRed() { digitalWrite(pinStatusGreenLED, LOW); digitalWrite(pinStatusRedLED, HIGH); digitalWrite(pinStatusYellowLED, LOW); } void ultraSonicDistanceRead() { // UltraSchall digitalWrite(trig_pin, LOW); // um Probleme mit potenziellen ECHOS zu vermeiden delay(5); // um Probleme mit potenziellen ECHOS zu vermeiden digitalWrite(trig_pin, HIGH); delayMicroseconds(10); digitalWrite(trig_pin, LOW); long echoTime = pulseIn(echo_pin, HIGH); long distanceUltraSonic = (echoTime / 2) * 0.03432; if (distanceUltraSonic > 30) { isPackageSpace = true; isPackageInside = false; } else if (distanceUltraSonic < 7) { isPackageSpace = false; isPackageInside = true; } else { isPackageSpace = true; isPackageInside = true; } }