Finish socket operations
This commit is contained in:
parent
9b49c3565d
commit
4c23565b9c
@ -31,9 +31,6 @@ struct EthernetConfiguration {
|
|||||||
// The IP address of the DNS server, if DHCP fails
|
// The IP address of the DNS server, if DHCP fails
|
||||||
uint8_t manualDnsAddress[4];
|
uint8_t manualDnsAddress[4];
|
||||||
|
|
||||||
uint32_t socketHeartbeatIntervalMs;
|
|
||||||
uint32_t socketHeartbeatTimeoutMs;
|
|
||||||
uint8_t socketHeartbeatFailureReconnectCount;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KeyConfiguration {
|
struct KeyConfiguration {
|
||||||
@ -88,23 +85,11 @@ private:
|
|||||||
currentChallengeExpiry = 0;
|
currentChallengeExpiry = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// MARK: Local client callbacks
|
||||||
* @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);
|
void handleLocalMessage(AsyncWebServerRequest *request);
|
||||||
|
|
||||||
bool convertHexMessageToBinary(const char* str);
|
// MARK: Socket Callbacks
|
||||||
|
|
||||||
void handleServerMessage(uint8_t* payload, size_t length);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Callback to send an error back to the server via the web socket.
|
* @brief Callback to send an error back to the server via the web socket.
|
||||||
@ -115,13 +100,60 @@ private:
|
|||||||
*/
|
*/
|
||||||
void sendServerError(MessageResult event);
|
void sendServerError(MessageResult event);
|
||||||
|
|
||||||
void processMessage(SignedMessage* message);
|
void handleServerMessage(uint8_t* payload, size_t length);
|
||||||
MessageResult verifyAndProcessReceivedMessage(SignedMessage* message);
|
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
// 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);
|
void prepareResponseBuffer(MessageResult event, Message* message = NULL);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send the prepared outgoing message to a locally connected client
|
||||||
|
*
|
||||||
|
* @param request The original request of the client
|
||||||
|
*/
|
||||||
void sendPreparedLocalResponse(AsyncWebServerRequest *request);
|
void sendPreparedLocalResponse(AsyncWebServerRequest *request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send the prepared outgoing message to the server
|
||||||
|
*/
|
||||||
void sendPreparedResponseToServer();
|
void sendPreparedResponseToServer();
|
||||||
|
|
||||||
void prepareChallenge(Message* message);
|
// MARK: Helper
|
||||||
void completeUnlockRequest(Message* message);
|
|
||||||
|
bool convertHexMessageToBinary(const char* str);
|
||||||
};
|
};
|
@ -28,6 +28,10 @@ struct ServerConfiguration {
|
|||||||
|
|
||||||
uint32_t reconnectTime;
|
uint32_t reconnectTime;
|
||||||
|
|
||||||
|
uint32_t socketHeartbeatIntervalMs;
|
||||||
|
uint32_t socketHeartbeatTimeoutMs;
|
||||||
|
uint8_t socketHeartbeatFailureReconnectCount;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ServerConnectionCallbacks {
|
class ServerConnectionCallbacks {
|
||||||
@ -51,11 +55,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
void configure(ServerConfiguration configuration, ServerConnectionCallbacks* callbacks);
|
void configure(ServerConfiguration configuration, ServerConnectionCallbacks* callbacks);
|
||||||
|
|
||||||
void connect();
|
/**
|
||||||
|
* @brief Call this function regularly to handle socket operations.
|
||||||
void disconnect();
|
*
|
||||||
|
* Connecting and disconnecting is done automatically.
|
||||||
void loop();
|
*
|
||||||
|
*/
|
||||||
|
void loop(uint32_t millis);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send a response message over the socket
|
* @brief Send a response message over the socket
|
||||||
@ -65,11 +71,24 @@ public:
|
|||||||
*/
|
*/
|
||||||
void sendResponse(uint8_t* buffer, uint16_t length);
|
void sendResponse(uint8_t* buffer, uint16_t length);
|
||||||
|
|
||||||
bool isSocketConnected() {
|
private:
|
||||||
|
|
||||||
|
uint32_t currentTime;
|
||||||
|
|
||||||
|
bool socketIsConnected() {
|
||||||
return webSocket.isConnected();
|
return webSocket.isConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
void connect();
|
||||||
|
|
||||||
|
void disconnect();
|
||||||
|
|
||||||
|
bool shouldReconnect = true;
|
||||||
|
uint32_t nextReconnectAttemptMs = 0;
|
||||||
|
|
||||||
|
void didDisconnect();
|
||||||
|
void didConnect();
|
||||||
|
|
||||||
|
|
||||||
ServerConfiguration configuration;
|
ServerConfiguration configuration;
|
||||||
|
|
||||||
|
@ -20,3 +20,4 @@ lib_deps =
|
|||||||
https://github.com/christophhagen/arduinoWebSockets#master
|
https://github.com/christophhagen/arduinoWebSockets#master
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
build_flags= -D WEBSOCKETS_NETWORK_TYPE=NETWORK_W5100
|
@ -62,10 +62,8 @@ void SesameController::configure(ServoConfiguration servoConfig, ServerConfigura
|
|||||||
|
|
||||||
void SesameController::loop(uint32_t millis) {
|
void SesameController::loop(uint32_t millis) {
|
||||||
currentTime = millis;
|
currentTime = millis;
|
||||||
server.loop();
|
server.loop(millis);
|
||||||
servo.loop(millis);
|
servo.loop(millis);
|
||||||
|
|
||||||
ensureWebSocketConnection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Local
|
// MARK: Local
|
||||||
@ -199,20 +197,6 @@ void SesameController::prepareResponseBuffer(MessageResult result, Message* mess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SesameController::ensureWebSocketConnection() {
|
|
||||||
/*
|
|
||||||
if (isReconnecting && WiFi.status() == WL_CONNECTED) {
|
|
||||||
isReconnecting = false;
|
|
||||||
Serial.print("WiFi IP address: ");
|
|
||||||
Serial.println(WiFi.localIP());
|
|
||||||
server.connect();
|
|
||||||
timeCheck.startNTP();
|
|
||||||
timeCheck.printLocalTime();
|
|
||||||
localWebServer.begin();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Helper
|
// MARK: Helper
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
15
src/main.cpp
15
src/main.cpp
@ -4,6 +4,15 @@
|
|||||||
*
|
*
|
||||||
* The code for a simple door unlock mechanism where a servo pushes on an existing
|
* The code for a simple door unlock mechanism where a servo pushes on an existing
|
||||||
* physical button.
|
* physical button.
|
||||||
|
*
|
||||||
|
* On compile error:
|
||||||
|
*
|
||||||
|
* In <Server.h>
|
||||||
|
*
|
||||||
|
* change:
|
||||||
|
* virtual void begin(uint16_t port=0) =0;
|
||||||
|
* to:
|
||||||
|
* virtual void begin() =0;
|
||||||
*/
|
*/
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
@ -35,6 +44,9 @@ void setup() {
|
|||||||
.path = serverPath,
|
.path = serverPath,
|
||||||
.key = serverAccessKey,
|
.key = serverAccessKey,
|
||||||
.reconnectTime = 5000,
|
.reconnectTime = 5000,
|
||||||
|
.socketHeartbeatIntervalMs = socketHeartbeatIntervalMs,
|
||||||
|
.socketHeartbeatTimeoutMs = socketHeartbeatTimeoutMs,
|
||||||
|
.socketHeartbeatFailureReconnectCount = socketHeartbeatFailureReconnectCount,
|
||||||
};
|
};
|
||||||
|
|
||||||
EthernetConfiguration ethernetConfig {
|
EthernetConfiguration ethernetConfig {
|
||||||
@ -47,9 +59,6 @@ void setup() {
|
|||||||
.dhcpLeaseResponseTimeoutMs = dhcpLeaseResponseTimeoutMs,
|
.dhcpLeaseResponseTimeoutMs = dhcpLeaseResponseTimeoutMs,
|
||||||
.manualIp = manualIpAddress,
|
.manualIp = manualIpAddress,
|
||||||
.manualDnsAddress = manualDnsServerAddress,
|
.manualDnsAddress = manualDnsServerAddress,
|
||||||
.socketHeartbeatIntervalMs = socketHeartbeatIntervalMs,
|
|
||||||
.socketHeartbeatTimeoutMs = socketHeartbeatTimeoutMs,
|
|
||||||
.socketHeartbeatFailureReconnectCount = socketHeartbeatFailureReconnectCount,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
KeyConfiguration keyConfig {
|
KeyConfiguration keyConfig {
|
||||||
|
@ -20,7 +20,8 @@ void ServerConnection::connect() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
webSocket.beginSSL(configuration.url, configuration.port, configuration.path);
|
webSocket.begin(configuration.url, configuration.port, configuration.path);
|
||||||
|
webSocket.setAuthorization(configuration.key);
|
||||||
|
|
||||||
std::function<void(WStype_t, uint8_t *, size_t)> f = [this](WStype_t type, uint8_t *payload, size_t length) {
|
std::function<void(WStype_t, uint8_t *, size_t)> f = [this](WStype_t type, uint8_t *payload, size_t length) {
|
||||||
this->webSocketEventHandler(type, payload, length);
|
this->webSocketEventHandler(type, payload, length);
|
||||||
@ -29,23 +30,41 @@ void ServerConnection::connect() {
|
|||||||
webSocket.setReconnectInterval(configuration.reconnectTime);
|
webSocket.setReconnectInterval(configuration.reconnectTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerConnection::didDisconnect() {
|
||||||
|
if (shouldReconnect) {
|
||||||
|
return; // Disconnect already registered.
|
||||||
|
}
|
||||||
|
Serial.println("[INFO] Socket disconnected");
|
||||||
|
nextReconnectAttemptMs = currentTime + configuration.socketHeartbeatIntervalMs;
|
||||||
|
shouldReconnect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerConnection::didConnect() {
|
||||||
|
Serial.println("[INFO] Socket connected");
|
||||||
|
webSocket.sendTXT(configuration.key);
|
||||||
|
webSocket.enableHeartbeat(configuration.socketHeartbeatIntervalMs, configuration.socketHeartbeatTimeoutMs, configuration.socketHeartbeatFailureReconnectCount);
|
||||||
|
}
|
||||||
|
|
||||||
void ServerConnection::disconnect() {
|
void ServerConnection::disconnect() {
|
||||||
webSocket.disconnect();
|
webSocket.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerConnection::loop() {
|
void ServerConnection::loop(uint32_t millis) {
|
||||||
|
currentTime = millis;
|
||||||
webSocket.loop();
|
webSocket.loop();
|
||||||
|
if (shouldReconnect) {
|
||||||
|
shouldReconnect = false;
|
||||||
|
connect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerConnection::webSocketEventHandler(WStype_t type, uint8_t * payload, size_t length) {
|
void ServerConnection::webSocketEventHandler(WStype_t type, uint8_t * payload, size_t length) {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case WStype_DISCONNECTED:
|
case WStype_DISCONNECTED:
|
||||||
Serial.println("[INFO] Socket disconnected.");
|
didDisconnect();
|
||||||
break;
|
break;
|
||||||
case WStype_CONNECTED:
|
case WStype_CONNECTED:
|
||||||
webSocket.sendTXT(configuration.key);
|
didConnect();
|
||||||
Serial.printf("[INFO] Socket connected to url: %s\n", payload);
|
|
||||||
webSocket.enableHeartbeat(pingInterval, pongTimeout, disconnectTimeoutCount);
|
|
||||||
break;
|
break;
|
||||||
case WStype_TEXT:
|
case WStype_TEXT:
|
||||||
controller->sendServerError(MessageResult::TextReceived);
|
controller->sendServerError(MessageResult::TextReceived);
|
||||||
@ -67,5 +86,7 @@ switch(type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ServerConnection::sendResponse(uint8_t* buffer, uint16_t length) {
|
void ServerConnection::sendResponse(uint8_t* buffer, uint16_t length) {
|
||||||
webSocket.sendBIN(buffer, length);
|
if (socketIsConnected()) {
|
||||||
|
webSocket.sendBIN(buffer, length);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user