#pragma once #include "server.h" #include "servo.h" #include "message.h" #include struct EthernetConfiguration { // The MAC address of the ethernet connection uint8_t macAddress[6]; // The master-in slave-out pin of the SPI connection for the Ethernet module int8_t spiPinMiso; // The master-out slave-in pin of the SPI connection for the Ethernet module int8_t spiPinMosi; // The slave clock pin of the SPI connection for the Ethernet module int8_t spiPinSclk; // The slave-select pin of the SPI connection for the Ethernet module int8_t spiPinSS; unsigned long dhcpLeaseTimeoutMs; unsigned long dhcpLeaseResponseTimeoutMs; // The static IP address to assign if DHCP fails uint8_t manualIp[4]; // The IP address of the DNS server, if DHCP fails uint8_t manualDnsAddress[4]; uint32_t socketHeartbeatIntervalMs; uint32_t socketHeartbeatTimeoutMs; uint8_t socketHeartbeatFailureReconnectCount; }; struct KeyConfiguration { const uint8_t* remoteKey; const uint8_t* localKey; uint32_t challengeExpiryMs; }; class SesameController: public ServerConnectionCallbacks { public: SesameController(uint16_t localWebServerPort); void configure(ServoConfiguration servoConfig, ServerConfiguration serverConfig, EthernetConfiguration ethernetConfig, KeyConfiguration keyConfig); void loop(uint32_t millis); private: uint32_t currentTime = 0; ServerConnection server; ServoController servo; AsyncWebServer localWebServer; EthernetConfiguration ethernetConfig; bool ethernetIsConfigured = false; KeyConfiguration keyConfig; bool isReconnecting = false; // Buffer to get local message SignedMessage receivedLocalMessage; uint32_t currentClientChallenge; uint32_t currentChallengeExpiry = 0; uint32_t currentServerChallenge; SignedMessage outgoingMessage; bool hasCurrentChallenge() { return currentChallengeExpiry > currentTime; } void clearCurrentChallenge() { currentClientChallenge = 0; currentServerChallenge = 0; currentChallengeExpiry = 0; } /** * @brief Send an error Response over the web socket. * * @param result The error result to send * @param discardMessage Indicate if the stored message should be cleared. * * Note: Only clear the message if no other operation is in progress. */ void sendErrorResponseToServer(MessageResult result, bool discardMessage = true); void ensureWebSocketConnection(); void handleLocalMessage(AsyncWebServerRequest *request); bool convertHexMessageToBinary(const char* str); void handleServerMessage(uint8_t* payload, size_t length); /** * @brief Callback to send an error back to the server via the web socket. * * This function is called when the socket get's an error. * * @param event The error to report back */ void sendServerError(MessageResult event); void processMessage(SignedMessage* message); MessageResult verifyAndProcessReceivedMessage(SignedMessage* message); void prepareResponseBuffer(MessageResult event, Message* message = NULL); void sendPreparedLocalResponse(AsyncWebServerRequest *request); void sendPreparedResponseToServer(); void prepareChallenge(Message* message); void completeUnlockRequest(Message* message); };