Use PlatformIO, fix EEPROM, send key index

This commit is contained in:
Christoph Hagen 2022-04-06 09:12:49 +02:00
parent e534958300
commit 35b171e0c4
2 changed files with 55 additions and 18 deletions

18
platformio.ini Normal file
View File

@ -0,0 +1,18 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:az-delivery-devkit-v4]
platform = espressif32
board = az-delivery-devkit-v4
framework = arduino
lib_deps =
links2004/WebSockets@^2.3.7
madhephaestus/ESP32Servo@^0.11.0
monitor_speed = 115200

View File

@ -13,9 +13,15 @@
#include <EEPROM.h> // To mark used keys as expired #include <EEPROM.h> // To mark used keys as expired
#include <ESP32Servo.h> // To control the servo #include <ESP32Servo.h> // To control the servo
// TODO:
// - Handle WiFi disconnect
// - Implement key sharing
// - Configure/diagnose over Bluetooth?
/* Settings */ /* Settings */
#define SERIAL_BAUD_RATE 115200
// The WiFi network to connect to // The WiFi network to connect to
constexpr const char* WIFI_SSID = "MyNetwork"; constexpr const char* WIFI_SSID = "MyNetwork";
constexpr const char* WIFI_PWD = "MyPassword"; constexpr const char* WIFI_PWD = "MyPassword";
@ -60,10 +66,10 @@ constexpr int servoPin = 14;
constexpr int servoFrequency = 50; constexpr int servoFrequency = 50;
// The microseconds to set the servo to the pressed state // The microseconds to set the servo to the pressed state
constexpr int PRESS_STATE_INTERVAL = 1550; constexpr int PRESS_STATE_INTERVAL = 1600;
// The microseconds to set the servo to the released state // The microseconds to set the servo to the released state
constexpr int RELEASE_STATE_INTERVAL = 1700; constexpr int RELEASE_STATE_INTERVAL = 1520;
/* Global variables */ /* Global variables */
@ -131,7 +137,7 @@ uint16_t indexOfNextUsableKey();
* @param keyIndex The index of the key in the 'keys' array. * @param keyIndex The index of the key in the 'keys' array.
* @return 0, if the key is unused, else non-zero. * @return 0, if the key is unused, else non-zero.
*/ */
uint8_t keyWasAlreadyUsed(uint16_t keyIndex); bool keyWasAlreadyUsed(uint16_t keyIndex);
/** /**
* Marks a key as used * Marks a key as used
@ -155,7 +161,7 @@ void markAllKeysUnused();
* Compares two keys in constant time * Compares two keys in constant time
* @return 1, if the keys are equal, else 0 * @return 1, if the keys are equal, else 0
*/ */
uint8_t keysAreEqual(const uint8_t* key1, const uint8_t* key2); bool keysAreEqual(const uint8_t* key1, const uint8_t* key2);
/* Servo management */ /* Servo management */
@ -174,15 +180,17 @@ void releaseButton();
/* Logic */ /* Logic */
/** /**
* Send a response event to the server. * Send a response event to the server and include the next key index.
* *
* Sends the event type as a single byte representing the raw event type. * Sends the event type as three byte.
* @param event The event type * @param event The event type
*/ */
void sendResponse(SesameEvent event) { void sendResponse(SesameEvent event) {
uint8_t response[1]; uint8_t response[3];
response[0] = static_cast<uint8_t>(event); response[0] = static_cast<uint8_t>(event);
webSocket.sendBIN(response, 1); response[1] = nextKeyIndex >> 8;
response[2] = nextKeyIndex & 0xFF;
webSocket.sendBIN(response, 3);
//webSocket.sendTXT(text); //webSocket.sendTXT(text);
Serial.printf("[INFO] Event %d\n", response[0]); Serial.printf("[INFO] Event %d\n", response[0]);
} }
@ -214,7 +222,7 @@ SesameEvent handleReceivedRequest(const uint8_t* payload, size_t length) {
return SesameEvent::InvalidKeyIndex; return SesameEvent::InvalidKeyIndex;
} }
if (!keysAreEqual(payload + 2, keys[keyIndex])) { if (!keysAreEqual(payload + 2, keys[keyIndex])) {
return SesameEvent::InvalidKeyIndex; return SesameEvent::InvalidKey;
} }
if (keyWasAlreadyUsed(keyIndex)) { if (keyWasAlreadyUsed(keyIndex)) {
return SesameEvent::KeyAlreadyUsed; return SesameEvent::KeyAlreadyUsed;
@ -226,6 +234,7 @@ SesameEvent handleReceivedRequest(const uint8_t* payload, size_t length) {
nextKeyIndex = keyIndex + 1; nextKeyIndex = keyIndex + 1;
// Move servo // Move servo
shouldStartOpening = true; shouldStartOpening = true;
Serial.printf("[Info] Used key %d\n", keyIndex);
return SesameEvent::KeyAccepted; return SesameEvent::KeyAccepted;
} }
@ -271,6 +280,8 @@ void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
case WStype_BIN: case WStype_BIN:
processReceivedBytes(payload, length); processReceivedBytes(payload, length);
break; break;
case WStype_PONG:
case WStype_PING:
case WStype_ERROR: case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START: case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START: case WStype_FRAGMENT_BIN_START:
@ -286,12 +297,13 @@ void setup() {
Serial.setDebugOutput(true); Serial.setDebugOutput(true);
Serial.println("[INFO] Device started"); Serial.println("[INFO] Device started");
markAllKeysUnused(); //markAllKeysUnused();
Serial.println("[WARN] All keys reset"); //Serial.println("[WARN] All keys reset");
ESP32PWM::allocateTimer(pwmTimer); ESP32PWM::allocateTimer(pwmTimer);
servo.setPeriodHertz(servoFrequency); servo.setPeriodHertz(servoFrequency);
servo.attach(servoPin); servo.attach(servoPin);
releaseButton();
Serial.println("[INFO] Servo configured"); Serial.println("[INFO] Servo configured");
Serial.printf("[INFO] Key security: %d bit (%d byte keys)\n", KEY_STRENGTH, KEY_BYTE_COUNT); Serial.printf("[INFO] Key security: %d bit (%d byte keys)\n", KEY_STRENGTH, KEY_BYTE_COUNT);
@ -306,17 +318,22 @@ void setup() {
} }
Serial.println("[INFO] WiFi connected"); Serial.println("[INFO] WiFi connected");
Serial.printf("[INFO] Opening socket %s%s on port %d\n", SERVER_URL, SERVER_PATH, SERVER_PORT);
#ifdef USE_SSL #ifdef USE_SSL
Serial.printf("[INFO] Opening SSL socket %s%s on port %d\n", SERVER_URL, SERVER_PATH, SERVER_PORT);
webSocket.beginSSL(SERVER_URL, SERVER_PORT, SERVER_PATH); webSocket.beginSSL(SERVER_URL, SERVER_PORT, SERVER_PATH);
#else #else
Serial.printf("[INFO] Opening insecure socket %s%s on port %d\n", SERVER_URL, SERVER_PATH, SERVER_PORT);
webSocket.begin(SERVER_URL, SERVER_PORT, SERVER_PATH); webSocket.begin(SERVER_URL, SERVER_PORT, SERVER_PATH);
#endif #endif
webSocket.onEvent(webSocketEvent); webSocket.onEvent(webSocketEvent);
// try again every 5000 ms if connection has failed // try again every 5000 ms if connection has failed
webSocket.setReconnectInterval(SOCKET_RECONNECT_TIME); webSocket.setReconnectInterval(SOCKET_RECONNECT_TIME);
// Creates an EEPROM fake in RAM, which is committed to flash
// The RAM data can be released by calling `EEPROM.end()`
EEPROM.begin(KEY_COUNT);
} }
void loop() { void loop() {
@ -345,29 +362,31 @@ uint16_t indexOfNextUsableKey() {
return 0; return 0;
} }
uint8_t keyWasAlreadyUsed(uint16_t keyIndex) { bool keyWasAlreadyUsed(uint16_t keyIndex) {
return EEPROM.read(keyIndex); return EEPROM.read(keyIndex) > 0;
} }
void markKeyUsed(uint16_t keyIndex) { void markKeyUsed(uint16_t keyIndex) {
EEPROM.write(keyIndex, 1); EEPROM.write(keyIndex, 1);
EEPROM.commit();
} }
void markAllKeysUnused() { void markAllKeysUnused() {
for (uint16_t keyIndex = 0; keyIndex < KEY_COUNT; keyIndex += 1) { for (uint16_t keyIndex = 0; keyIndex < KEY_COUNT; keyIndex += 1) {
EEPROM.write(keyIndex, 0); EEPROM.write(keyIndex, 0);
} }
EEPROM.commit();
} }
uint8_t keysAreEqual(const uint8_t* key1, const uint8_t* key2) { bool keysAreEqual(const uint8_t* key1, const uint8_t* key2) {
uint8_t result = 0; uint8_t result = 0;
for (uint8_t i = 0; i < KEY_BYTE_COUNT; i += 1) { for (uint8_t i = 0; i < KEY_BYTE_COUNT; i += 1) {
result |= key1[i] ^ key2[i]; result |= key1[i] ^ key2[i];
} }
if (result) { if (result) {
return 0; return false;
} }
return 1; return true;
} }
/* Servo management */ /* Servo management */