Use local UDP messages instead of web server
This commit is contained in:
parent
4a88d1a380
commit
1504ce6b0c
@ -28,4 +28,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];
|
||||||
|
|
||||||
|
// The port for the incoming UDP connection
|
||||||
|
uint16_t udpPort;
|
||||||
};
|
};
|
@ -3,14 +3,13 @@
|
|||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "servo.h"
|
#include "servo.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include "configurations/EthernetConfiguration.h"
|
#include "configurations/EthernetConfiguration.h"
|
||||||
#include "configurations/KeyConfiguration.h"
|
#include "configurations/KeyConfiguration.h"
|
||||||
|
|
||||||
class SesameController: public ServerConnectionCallbacks {
|
class SesameController: public ServerConnectionCallbacks {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SesameController(uint16_t localWebServerPort);
|
SesameController();
|
||||||
|
|
||||||
void configure(ServoConfiguration servoConfig, ServerConfiguration serverConfig, EthernetConfiguration ethernetConfig, KeyConfiguration keyConfig);
|
void configure(ServoConfiguration servoConfig, ServerConfiguration serverConfig, EthernetConfiguration ethernetConfig, KeyConfiguration keyConfig);
|
||||||
|
|
||||||
@ -22,7 +21,16 @@ private:
|
|||||||
|
|
||||||
ServerConnection server;
|
ServerConnection server;
|
||||||
ServoController servo;
|
ServoController servo;
|
||||||
AsyncWebServer localWebServer;
|
|
||||||
|
// UDP
|
||||||
|
|
||||||
|
// buffers for receiving and sending data
|
||||||
|
char udpReceiveBuffer[SIGNED_MESSAGE_SIZE]; // buffer to hold incoming packet
|
||||||
|
|
||||||
|
// An EthernetUDP instance to send and receive packets over UDP
|
||||||
|
EthernetUDP Udp;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EthernetConfiguration ethernetConfig;
|
EthernetConfiguration ethernetConfig;
|
||||||
bool ethernetIsConfigured = false;
|
bool ethernetIsConfigured = false;
|
||||||
@ -52,7 +60,7 @@ private:
|
|||||||
|
|
||||||
// MARK: Local client callbacks
|
// MARK: Local client callbacks
|
||||||
|
|
||||||
void handleLocalMessage(AsyncWebServerRequest *request);
|
void checkLocalMessage();
|
||||||
|
|
||||||
// MARK: Socket Callbacks
|
// MARK: Socket Callbacks
|
||||||
|
|
||||||
@ -76,7 +84,7 @@ private:
|
|||||||
*
|
*
|
||||||
* Note: Prepares the response in the outgoing message buffer.
|
* Note: Prepares the response in the outgoing message buffer.
|
||||||
*/
|
*/
|
||||||
void processMessage(SignedMessage* message);
|
void processMessage(SignedMessage* message, bool shouldPerformUnlock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Checks that the message is valid and prepares a challenge.
|
* @brief Checks that the message is valid and prepares a challenge.
|
||||||
@ -105,7 +113,7 @@ private:
|
|||||||
*
|
*
|
||||||
* Note: Prepares the response in the outgoing message buffer.
|
* Note: Prepares the response in the outgoing message buffer.
|
||||||
*/
|
*/
|
||||||
void completeUnlockRequest(Message* message);
|
void completeUnlockRequest(Message* message, bool shouldPerformUnlock);
|
||||||
|
|
||||||
// MARK: Responses
|
// MARK: Responses
|
||||||
|
|
||||||
@ -117,12 +125,18 @@ private:
|
|||||||
*/
|
*/
|
||||||
void prepareResponseBuffer(MessageResult event, Message* message = NULL);
|
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
|
* @brief Send the prepared outgoing message to a locally connected client
|
||||||
*
|
*
|
||||||
* @param request The original request of the client
|
* @param request The original request of the client
|
||||||
*/
|
*/
|
||||||
void sendPreparedLocalResponse(AsyncWebServerRequest *request);
|
void sendPreparedLocalResponse();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send the prepared outgoing message to the server
|
* @brief Send the prepared outgoing message to the server
|
||||||
@ -131,5 +145,5 @@ private:
|
|||||||
|
|
||||||
// MARK: Helper
|
// MARK: Helper
|
||||||
|
|
||||||
bool convertHexMessageToBinary(const char* str);
|
bool convertHexMessageToBinary(const char* str);
|
||||||
};
|
};
|
@ -13,9 +13,7 @@ platform = espressif32
|
|||||||
board = az-delivery-devkit-v4
|
board = az-delivery-devkit-v4
|
||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps =
|
lib_deps =
|
||||||
; links2004/WebSockets@^2.4.0
|
|
||||||
madhephaestus/ESP32Servo@^1.1.0
|
madhephaestus/ESP32Servo@^1.1.0
|
||||||
ottowinter/ESPAsyncWebServer-esphome@^3.0.0
|
|
||||||
arduino-libraries/Ethernet@^2.0.2
|
arduino-libraries/Ethernet@^2.0.2
|
||||||
https://github.com/christophhagen/arduinoWebSockets#master
|
https://github.com/christophhagen/arduinoWebSockets#master
|
||||||
rweather/Crypto@^0.4.0
|
rweather/Crypto@^0.4.0
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <Ethernet.h>
|
#include <Ethernet.h>
|
||||||
|
|
||||||
SesameController::SesameController(uint16_t localWebServerPort) : localWebServer(localWebServerPort) {
|
SesameController::SesameController() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,41 +51,54 @@ void SesameController::configure(ServoConfiguration servoConfig, ServerConfigura
|
|||||||
// Direct messages and errors over the websocket to the controller
|
// Direct messages and errors over the websocket to the controller
|
||||||
server.configure(serverConfig, this);
|
server.configure(serverConfig, this);
|
||||||
Serial.println("[INFO] Server connection configured");
|
Serial.println("[INFO] Server connection configured");
|
||||||
|
|
||||||
// Direct messages from the local web server to the controller
|
|
||||||
localWebServer.on("/message", HTTP_POST, [this] (AsyncWebServerRequest *request) {
|
|
||||||
this->handleLocalMessage(request);
|
|
||||||
this->sendPreparedLocalResponse(request);
|
|
||||||
});
|
|
||||||
|
|
||||||
Serial.println("[INFO] Local web server configured");
|
Udp.begin(ethernetConfig.udpPort);
|
||||||
|
Serial.println("[INFO] Local UDP connection configured");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SesameController::loop(uint32_t millis) {
|
void SesameController::loop(uint32_t millis) {
|
||||||
currentTime = millis;
|
currentTime = millis;
|
||||||
server.loop(millis);
|
//server.loop(millis);
|
||||||
|
|
||||||
|
checkLocalMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Local
|
// MARK: Local
|
||||||
|
|
||||||
void SesameController::handleLocalMessage(AsyncWebServerRequest *request) {
|
void SesameController::checkLocalMessage() {
|
||||||
if (!request->hasParam(messageUrlParameter)) {
|
if (readLocalMessage()) {
|
||||||
Serial.println("Missing url parameter");
|
sendPreparedLocalResponse();
|
||||||
prepareResponseBuffer(MessageResult::InvalidUrlParameter);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
String encoded = request->getParam(messageUrlParameter)->value();
|
|
||||||
if (!convertHexMessageToBinary(encoded.c_str())) {
|
|
||||||
Serial.println("Invalid hex encoding");
|
|
||||||
prepareResponseBuffer(MessageResult::InvalidMessageSizeFromRemote);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
processMessage(&receivedLocalMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SesameController::sendPreparedLocalResponse(AsyncWebServerRequest *request) {
|
bool SesameController::readLocalMessage() {
|
||||||
request->send_P(200, "application/octet-stream", (uint8_t*) &outgoingMessage, SIGNED_MESSAGE_SIZE);
|
// if there's data available, read a packet
|
||||||
Serial.printf("[INFO] Local response %u,%u\n", outgoingMessage.message.messageType, outgoingMessage.message.result);
|
int packetSize = Udp.parsePacket();
|
||||||
|
if (packetSize == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (packetSize != SIGNED_MESSAGE_SIZE) {
|
||||||
|
Serial.print("Received packet of invalid size ");
|
||||||
|
Serial.println(packetSize);
|
||||||
|
prepareResponseBuffer(MessageResult::InvalidMessageSizeFromRemote);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int bytesRead = Udp.read((uint8_t*) &receivedLocalMessage, SIGNED_MESSAGE_SIZE);
|
||||||
|
if (bytesRead != SIGNED_MESSAGE_SIZE) {
|
||||||
|
Serial.println("Failed to read full local message");
|
||||||
|
prepareResponseBuffer(MessageResult::InvalidMessageSizeFromRemote);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Serial.println("Received local message");
|
||||||
|
processMessage(&receivedLocalMessage, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SesameController::sendPreparedLocalResponse() {
|
||||||
|
// send a reply to the IP address and port that sent us the packet we received
|
||||||
|
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
|
||||||
|
Udp.write((uint8_t*) &outgoingMessage, SIGNED_MESSAGE_SIZE);
|
||||||
|
Udp.endPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Server
|
// MARK: Server
|
||||||
@ -101,7 +114,7 @@ void SesameController::handleServerMessage(uint8_t* payload, size_t length) {
|
|||||||
sendServerError(MessageResult::InvalidMessageSizeFromRemote);
|
sendServerError(MessageResult::InvalidMessageSizeFromRemote);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
processMessage((SignedMessage*) payload);
|
processMessage((SignedMessage*) payload, true);
|
||||||
sendPreparedResponseToServer();
|
sendPreparedResponseToServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +125,7 @@ void SesameController::sendPreparedResponseToServer() {
|
|||||||
|
|
||||||
// MARK: Message handling
|
// MARK: Message handling
|
||||||
|
|
||||||
void SesameController::processMessage(SignedMessage* message) {
|
void SesameController::processMessage(SignedMessage* message, bool shouldPerformUnlock) {
|
||||||
// Result must be empty
|
// Result must be empty
|
||||||
if (message->message.result != MessageResult::MessageAccepted) {
|
if (message->message.result != MessageResult::MessageAccepted) {
|
||||||
prepareResponseBuffer(MessageResult::InvalidMessageResultFromRemote);
|
prepareResponseBuffer(MessageResult::InvalidMessageResultFromRemote);
|
||||||
@ -127,7 +140,7 @@ void SesameController::processMessage(SignedMessage* message) {
|
|||||||
checkAndPrepareChallenge(&message->message);
|
checkAndPrepareChallenge(&message->message);
|
||||||
return;
|
return;
|
||||||
case MessageType::request:
|
case MessageType::request:
|
||||||
completeUnlockRequest(&message->message);
|
completeUnlockRequest(&message->message, shouldPerformUnlock);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
prepareResponseBuffer(MessageResult::InvalidMessageTypeFromRemote);
|
prepareResponseBuffer(MessageResult::InvalidMessageTypeFromRemote);
|
||||||
@ -158,7 +171,7 @@ void SesameController::prepareChallenge(Message* message) {
|
|||||||
prepareResponseBuffer(MessageResult::MessageAccepted, message);
|
prepareResponseBuffer(MessageResult::MessageAccepted, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SesameController::completeUnlockRequest(Message* message) {
|
void SesameController::completeUnlockRequest(Message* message, bool shouldPerformUnlock) {
|
||||||
// Client and server challenge must match
|
// Client and server challenge must match
|
||||||
if (message->clientChallenge != currentClientChallenge) {
|
if (message->clientChallenge != currentClientChallenge) {
|
||||||
prepareResponseBuffer(MessageResult::InvalidClientChallengeFromRemote, message);
|
prepareResponseBuffer(MessageResult::InvalidClientChallengeFromRemote, message);
|
||||||
@ -180,7 +193,9 @@ void SesameController::completeUnlockRequest(Message* message) {
|
|||||||
clearCurrentChallenge();
|
clearCurrentChallenge();
|
||||||
|
|
||||||
// Move servo
|
// Move servo
|
||||||
servo.pressButton();
|
if (shouldPerformUnlock) {
|
||||||
|
servo.pressButton();
|
||||||
|
}
|
||||||
prepareResponseBuffer(MessageResult::MessageAccepted, message);
|
prepareResponseBuffer(MessageResult::MessageAccepted, message);
|
||||||
Serial.println("[INFO] Accepted message");
|
Serial.println("[INFO] Accepted message");
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
SesameController controller(localPort);
|
SesameController controller{};
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(serialBaudRate);
|
Serial.begin(serialBaudRate);
|
||||||
@ -59,6 +59,7 @@ void setup() {
|
|||||||
.dhcpLeaseResponseTimeoutMs = dhcpLeaseResponseTimeoutMs,
|
.dhcpLeaseResponseTimeoutMs = dhcpLeaseResponseTimeoutMs,
|
||||||
.manualIp = manualIpAddress,
|
.manualIp = manualIpAddress,
|
||||||
.manualDnsAddress = manualDnsServerAddress,
|
.manualDnsAddress = manualDnsServerAddress,
|
||||||
|
.udpPort = localUdpPort,
|
||||||
};
|
};
|
||||||
|
|
||||||
KeyConfiguration keyConfig {
|
KeyConfiguration keyConfig {
|
||||||
|
Loading…
Reference in New Issue
Block a user