#pragma once #include "server.h" #include "servo.h" #include "message.h" #include "configurations/EthernetConfiguration.h" #include "configurations/KeyConfiguration.h" enum class SesameDeviceStatus { /** * @brief The initial state of the device after boot */ initial, /** * @brief The device has configured the individual parts, * but has no the ethernet hardware detected. */ configuredButNoEthernetHardware, /** * @brief The device has ethernet hardware, but no ethernet link */ ethernetHardwareButNoLink, /** * @brief The device has an ethernet link, but no IP address. */ ethernetLinkButNoIP, /** * @brief The device has an IP address, but no socket connection */ ipAddressButNoSocketConnection, }; class SesameController: public ServerConnectionCallbacks { public: SesameController(ServoConfiguration servoConfig, ServerConfiguration serverConfig, EthernetConfiguration ethernetConfig, KeyConfiguration keyConfig); void loop(uint32_t millis); private: SesameDeviceStatus status = SesameDeviceStatus::initial; uint32_t currentTime = 0; ServerConnection server; ServoController servo; // UDP // An EthernetUDP instance to send and receive packets over UDP EthernetUDP udp; EthernetHardwareStatus ethernetStatus; 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; // MARK: Ethernet void initializeSpiBusForEthernetModule(); /** * @brief Checks to ensure that Ethernet hardware is available * * @return true The hardware is available * @return false The hardware is missing */ bool hasAvailableEthernetHardware(); /** * @brief Check that an active ethernet link is available * * @return true Link is available * @return false Link is absent */ bool hasEthernetLink(); void configureEthernet(); void startUDP(); void stopUDP(); bool hasCurrentChallenge() { return currentChallengeExpiry > currentTime; } void clearCurrentChallenge() { currentClientChallenge = 0; currentServerChallenge = 0; currentChallengeExpiry = 0; } // MARK: Local client callbacks void checkLocalMessage(); // MARK: Socket Callbacks /** * @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 handleServerMessage(uint8_t* payload, size_t length); // MARK: Message processing /** * @brief Process a received message (local or socket). * * @param message The message to process. * * Note: Prepares the response in the outgoing message buffer. */ void processMessage(SignedMessage* message, bool shouldPerformUnlock); /** * @brief Checks that the message is valid and prepares a challenge. * * This function is also called when a challenge response arrives too late. * * @param message The message to respond to * * Note: Prepares the response in the outgoing message buffer. */ void checkAndPrepareChallenge(Message* message); /** * @brief Prepare a server challenge for a local or socket message. * * @param message The message to respond to * * Note: Prepares the response in the outgoing message buffer. */ void prepareChallenge(Message* message); /** * @brief Complete an unlock request for a local or socket message. * * @param message The message to respond to * * Note: Prepares the response in the outgoing message buffer. */ void completeUnlockRequest(Message* message, bool shouldPerformUnlock); // MARK: Responses /** * @brief Prepare the outgoing message buffer for both socket and local responses. * * @param event The resulting state to transmit * @param message An optional message to echo */ void prepareResponseBuffer(MessageResult event, Message* message = NULL); /** * @brief Read a message from the UDP port * */ bool readLocalMessage(); /** * @brief Send the prepared outgoing message to a locally connected client * * @param request The original request of the client */ void sendPreparedLocalResponse(); /** * @brief Send the prepared outgoing message to the server */ void sendPreparedResponseToServer(); // MARK: Helper bool convertHexMessageToBinary(const char* str); };