diff --git a/src/FabReader_v2/.vscode/settings.json b/src/FabReader_v2/.vscode/settings.json index c51607b..1610e0a 100644 --- a/src/FabReader_v2/.vscode/settings.json +++ b/src/FabReader_v2/.vscode/settings.json @@ -10,6 +10,7 @@ "string": "cpp", "functional": "cpp", "*.desfire": "cpp", - "*.old": "cpp" + "*.old": "cpp", + "*.deprecated": "cpp" } } \ No newline at end of file diff --git a/src/FabReader_v2/README.txt b/src/FabReader_v2/README.txt index bd2911a..baed9cd 100644 --- a/src/FabReader_v2/README.txt +++ b/src/FabReader_v2/README.txt @@ -1,3 +1,4 @@ +# OTA ## Protocol: READERID is 5 Digits 1. Hello: Topic="fabreader", Payload="READERID" @@ -21,4 +22,9 @@ Repeat Request and Response until: "Cancel" -> to Server If FabReader works as deadmen switch the OTA connection is not stopped and the next check can be started with restartOTA. -If DESFire Card uses Random UID the UID changes every new connection, so the connections stays active until the server restartsOTA and performs new OTA. \ No newline at end of file +If DESFire Card uses Random UID the UID changes every new connection, so the connections stays active until the server restartsOTA and performs new OTA. + +# Display +## Protocol +1. Title: Topic="fabreader/READERID/display/title", Payload=Title Text +2. Info: Topic="fabreader/READERID/display/info", Payload=Info Text \ No newline at end of file diff --git a/src/FabReader_v2/platformio.ini b/src/FabReader_v2/platformio.ini index f96f99f..a3f3403 100644 --- a/src/FabReader_v2/platformio.ini +++ b/src/FabReader_v2/platformio.ini @@ -18,3 +18,6 @@ lib_deps = thingpulse/ESP8266 and ESP32 OLED driver for SSD1306 displays@^4.3.0 miguelbalboa/MFRC522@^1.4.10 thijse/ArduinoLog@^1.1.1 + uipethernet/UIPEthernet@^2.0.12 + bblanchon/ArduinoJson@^6.19.4 + mbed-feb11/Crypto@0.0.0+sha.f04410cef037 diff --git a/src/FabReader_v2/src/Display.cpp b/src/FabReader_v2/src/Display.cpp index e69de29..9be1013 100644 --- a/src/FabReader_v2/src/Display.cpp +++ b/src/FabReader_v2/src/Display.cpp @@ -0,0 +1,100 @@ +#include "display.h" +#include + +Display::Display(int sda, int scl, int readerid) +{ + this->readerid = readerid; + display = new SSD1306Wire(0x3c, sda, scl); + display->init(); + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->flipScreenVertically(); +} + +void Display::clearReaderInfo() +{ + char buffer [DISPLAY_BUFFER_SIZE]; + sprintf(buffer, "%05d", readerid); + writeReaderInfo(buffer); +} + +void Display::createReaderInfo(char state[]) +{ + if(strlen(state) < DISPLAY_BUFFER_SIZE - 1 - 6) + { + char buffer [DISPLAY_BUFFER_SIZE]; + sprintf(buffer, "%s %05d", state, readerid); + writeReaderInfo(buffer); + } +} + +void Display::writeReaderInfo(char text[]) +{ + if(strlen(text) < DISPLAY_BUFFER_SIZE - 1) + { + strcpy(ReaderInfo, text); + } + updateDisplay(); +} + +void Display::writeTitle(char text[]) +{ + if(strlen(text) < DISPLAY_BUFFER_SIZE - 1) + { + strcpy(Title, text); + } + updateDisplay(); +} + +void Display::writeInfo(char text[]) +{ + if(strlen(text) < DISPLAY_BUFFER_SIZE - 1) + { + strcpy(Info, text); + } + + updateDisplay(); +} + +void Display::updateDisplay() +{ + display->clear(); + + display->setFont(ArialMT_Plain_10); + display->drawString(64, 0, ReaderInfo); + + display->setFont(ArialMT_Plain_24); + display->drawString(64, 13, Title); + + display->setFont(ArialMT_Plain_16); + display->drawString(64, 40, Info); + + display->display(); +} + +void Display::updateByMQTT(char* topic, byte* payload, unsigned int length) +{ + char topic_displayTitle[] = "fabreader/00000/display/title"; + sprintf(topic_displayTitle, "fabreader/%05d/display/title", readerid); + + char topic_displayInfo[] = "fabreader/00000/display/info"; + sprintf(topic_displayInfo, "fabreader/%05d/display/info", readerid); + + char topic_stopOTA[] = "fabreader/00000/stopOTA"; + sprintf(topic_stopOTA, "fabreader/%05d/stopOTA", readerid); + + char buffer[length + 1] = {0}; + memcpy(buffer, payload, length); + + if(!strcmp(topic, topic_displayTitle)) + { + writeTitle(buffer); + } + else if(!strcmp(topic, topic_displayInfo)) + { + writeInfo(buffer); + } + else if(!strcmp(topic, topic_stopOTA)) + { + clearReaderInfo(); + } +} \ No newline at end of file diff --git a/src/FabReader_v2/src/Display.h b/src/FabReader_v2/src/Display.h index 5cf31c5..2514fb1 100644 --- a/src/FabReader_v2/src/Display.h +++ b/src/FabReader_v2/src/Display.h @@ -1,21 +1,26 @@ #ifndef DISPLAY_H #define DISPLAY_H -enum State +#include + +#define DISPLAY_BUFFER_SIZE 30 + +class Display { - CONNECT_WIFI, - CONNECT_MQTT, - FREE, - INUSE, - AUTHORIZE + private: + SSD1306Wire* display; + int readerid; + char ReaderInfo[DISPLAY_BUFFER_SIZE] = ""; + char Title[DISPLAY_BUFFER_SIZE] = "Boot ..."; + char Info[DISPLAY_BUFFER_SIZE] = ""; + + public: + Display(int sda, int scl, int readerid); + void createReaderInfo(char* state); + void clearReaderInfo(); + void writeReaderInfo(char* text); + void writeTitle(char* text); + void writeInfo(char* text); + void updateDisplay(); + void updateByMQTT(char* topic, byte* payload, unsigned int length); }; - -String Messages [] = -{ - "Connecting to WIFI ...", - "Connecting to MQTT ...", - "Free", - "In Use", - "Authorize ..." -} - #endif \ No newline at end of file diff --git a/src/FabReader_v2/src/OTAProxy.cpp b/src/FabReader_v2/src/OTAProxy.cpp index 5e1e503..e6b567b 100644 --- a/src/FabReader_v2/src/OTAProxy.cpp +++ b/src/FabReader_v2/src/OTAProxy.cpp @@ -1,5 +1,5 @@ -#include "OTAProxy.h" -#include "NFC.h" +#include "otaproxy.h" +#include "nfc.h" #include OTAProxy::OTAProxy(PubSubClient* mqttClient, NFC* nfc, int id) diff --git a/src/FabReader_v2/src/OTAProxy.h b/src/FabReader_v2/src/OTAProxy.h index 3fb1c24..8245b6d 100644 --- a/src/FabReader_v2/src/OTAProxy.h +++ b/src/FabReader_v2/src/OTAProxy.h @@ -2,7 +2,7 @@ #define OTAProxy_H #include -#include "NFC.h" +#include "nfc.h" #define MSG_BUFFER_SIZE 50 class OTAProxy diff --git a/src/FabReader_v2/src/Pins.h b/src/FabReader_v2/src/Pins.h index f6e195f..958c6f8 100644 --- a/src/FabReader_v2/src/Pins.h +++ b/src/FabReader_v2/src/Pins.h @@ -2,8 +2,8 @@ #define PINS_H // Pins for ESP8266 -#define PIN_SDA 5 -#define PIN_SCL 4 +#define PIN_SDA 4 +#define PIN_SCL 5 #define PIN_SPI_MOSI 13 #define PIN_SPI_MISO 12 diff --git a/src/FabReader_v2/src/main.cpp b/src/FabReader_v2/src/main.cpp index 84fe2c3..a612b15 100644 --- a/src/FabReader_v2/src/main.cpp +++ b/src/FabReader_v2/src/main.cpp @@ -7,6 +7,7 @@ #include "otaproxy.h" #include "helpers.h" #include "Desfire.h" +#include "display.h" #include #include @@ -14,7 +15,6 @@ #include #include #include -#include WiFiClient espClient; //Config_Data config; @@ -22,6 +22,7 @@ WiFiClient espClient; PubSubClient* mqtt; NFC* nfc; OTAProxy* ota; +Display* display; unsigned long otatimeout = 3000; unsigned long lastotatime; @@ -65,7 +66,19 @@ void reconnect() char topic_stopOTA[] = "fabreader/00000/stopOTA"; sprintf(topic_stopOTA, "fabreader/%05d/stopOTA", FABREADERID); mqtt->subscribe(topic_stopOTA); - } else { + + char topic_display[] = "fabreader/00000/display/#"; + sprintf(topic_display, "fabreader/%05d/display/#", FABREADERID); + mqtt->subscribe(topic_display); + + display->writeTitle("Connected"); + display->writeInfo(""); + } + else + { + display->writeTitle("Reconnect"); + display->writeInfo("MQTT"); + Serial.print("failed, rc="); Serial.print(mqtt->state()); Serial.println(" try again in 5 seconds"); @@ -82,6 +95,7 @@ void callback(char* topic, byte* payload, unsigned int length) { ota->continueOTA(topic, payload, length); } + display->updateByMQTT(topic, payload, length); } void setup() @@ -95,6 +109,10 @@ void setup() pinMode(PIN_ETH_SPI_SS, OUTPUT); digitalWrite(PIN_ETH_SPI_SS, HIGH); + display = new Display(PIN_SDA, PIN_SCL, FABREADERID); + display->clearReaderInfo(); + + display->writeInfo("Start NFC ..."); Serial.println("Connecting NFC ..."); nfc = new NFC(PIN_RFID_SPI_SS, PIN_RFID_RST); if(!(nfc->rfid->PCD_PerformSelfTest())) @@ -103,12 +121,15 @@ void setup() } Serial.println("NFC connected"); + display->writeInfo("Start WIFI ..."); setup_wifi(); + display->writeInfo("Start MQTT ..."); mqtt = new PubSubClient(espClient); mqtt->setServer(MQTT_BROKER, 1883); mqtt->setCallback(callback); + display->writeInfo("Start OTA ..."); ota = new OTAProxy(mqtt, nfc, FABREADERID); } @@ -129,8 +150,14 @@ void loop() { Serial.println("Card connected"); lastotatime = millis(); + + display->createReaderInfo("Run OTA"); ota->startOTA(); } + else + { + display->createReaderInfo("Retry Card"); + } } } if(ota->hasActiveOTA()) @@ -138,6 +165,7 @@ void loop() if(millis() - lastotatime > otatimeout) { ota->cancelOTA(); + display->clearReaderInfo(); } } } \ No newline at end of file diff --git a/src/FabReader_v2/src/main.cpp.display b/src/FabReader_v2/src/main.cpp.display new file mode 100644 index 0000000..b1393b9 --- /dev/null +++ b/src/FabReader_v2/src/main.cpp.display @@ -0,0 +1,189 @@ +/** + The MIT License (MIT) + + Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + Copyright (c) 2018 by Fabrice Weinberg + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + ThingPulse invests considerable time and money to develop these open source libraries. + Please support us by buying our products (and not the clones) from + https://thingpulse.com + +*/ + +// Include the correct display library + +// For a connection via I2C using the Arduino Wire include: +#include // Only needed for Arduino 1.6.5 and earlier +#include "SSD1306Wire.h" // legacy: #include "SSD1306.h" +// OR #include "SH1106Wire.h" // legacy: #include "SH1106.h" + +// For a connection via I2C using brzo_i2c (must be installed) include: +// #include // Only needed for Arduino 1.6.5 and earlier +// #include "SSD1306Brzo.h" +// OR #include "SH1106Brzo.h" + +// For a connection via SPI include: +// #include // Only needed for Arduino 1.6.5 and earlier +// #include "SSD1306Spi.h" +// OR #include "SH1106SPi.h" + + + +// Initialize the OLED display using Arduino Wire: +SSD1306Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL - SDA and SCL usually populate automatically based on your board's pins_arduino.h e.g. https://github.com/esp8266/Arduino/blob/master/variants/nodemcu/pins_arduino.h +// SSD1306Wire display(0x3c, D3, D5); // ADDRESS, SDA, SCL - If not, they can be specified manually. +// SSD1306Wire display(0x3c, SDA, SCL, GEOMETRY_128_32); // ADDRESS, SDA, SCL, OLEDDISPLAY_GEOMETRY - Extra param required for 128x32 displays. +// SH1106Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL + +// Initialize the OLED display using brzo_i2c: +// SSD1306Brzo display(0x3c, D3, D5); // ADDRESS, SDA, SCL +// or +// SH1106Brzo display(0x3c, D3, D5); // ADDRESS, SDA, SCL + +// Initialize the OLED display using SPI: +// D5 -> CLK +// D7 -> MOSI (DOUT) +// D0 -> RES +// D2 -> DC +// D8 -> CS +// SSD1306Spi display(D0, D2, D8); // RES, DC, CS +// or +// SH1106Spi display(D0, D2); // RES, DC + + +#define DEMO_DURATION 3000 +typedef void (*Demo)(void); + +int demoMode = 0; +int counter = 1; + +void setup() { + Serial.begin(115200); + Serial.println(); + Serial.println(); + + + // Initialising the UI will init the display too. + display.init(); + + display.flipScreenVertically(); + display.setFont(ArialMT_Plain_10); + +} + +void drawFontFaceDemo() { + // Font Demo1 + // create more fonts at http://oleddisplay.squix.ch/ + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.setFont(ArialMT_Plain_10); + display.drawString(0, 0, "Hello world"); + display.setFont(ArialMT_Plain_16); + display.drawString(0, 10, "Hello world"); + display.setFont(ArialMT_Plain_24); + display.drawString(0, 26, "Hello world"); +} + +void drawTextFlowDemo() { + display.setFont(ArialMT_Plain_10); + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.drawStringMaxWidth(0, 0, 128, + "Lorem ipsum\n dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore." ); +} + +void drawTextAlignmentDemo() { + // Text alignment demo + display.setFont(ArialMT_Plain_10); + + // The coordinates define the left starting point of the text + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.drawString(0, 10, "Left aligned (0,10)"); + + // The coordinates define the center of the text + display.setTextAlignment(TEXT_ALIGN_CENTER); + display.drawString(64, 22, "Center aligned (64,22)"); + + // The coordinates define the right end of the text + display.setTextAlignment(TEXT_ALIGN_RIGHT); + display.drawString(128, 33, "Right aligned (128,33)"); +} + +void drawRectDemo() { + // Draw a pixel at given position + for (int i = 0; i < 10; i++) { + display.setPixel(i, i); + display.setPixel(10 - i, i); + } + display.drawRect(12, 12, 20, 20); + + // Fill the rectangle + display.fillRect(14, 14, 17, 17); + + // Draw a line horizontally + display.drawHorizontalLine(0, 40, 20); + + // Draw a line horizontally + display.drawVerticalLine(40, 0, 20); +} + +void drawCircleDemo() { + for (int i = 1; i < 8; i++) { + display.setColor(WHITE); + display.drawCircle(32, 32, i * 3); + if (i % 2 == 0) { + display.setColor(BLACK); + } + display.fillCircle(96, 32, 32 - i * 3); + } +} + +void drawProgressBarDemo() { + int progress = (counter / 5) % 100; + // draw the progress bar + display.drawProgressBar(0, 32, 120, 10, progress); + + // draw the percentage as String + display.setTextAlignment(TEXT_ALIGN_CENTER); + display.drawString(64, 15, String(progress) + "%"); +} + +Demo demos[] = {drawFontFaceDemo, drawTextFlowDemo, drawTextAlignmentDemo, drawRectDemo, drawCircleDemo, drawProgressBarDemo}; +int demoLength = (sizeof(demos) / sizeof(Demo)); +long timeSinceLastModeSwitch = 0; + +void loop() { + // clear the display + display.clear(); + // draw the current demo method + demos[demoMode](); + + display.setFont(ArialMT_Plain_10); + display.setTextAlignment(TEXT_ALIGN_RIGHT); + display.drawString(128, 54, String(millis())); + // write the buffer to the display + display.display(); + + if (millis() - timeSinceLastModeSwitch > DEMO_DURATION) { + demoMode = (demoMode + 1) % demoLength; + timeSinceLastModeSwitch = millis(); + } + counter++; + delay(10); +}