New state machine, local UDP route
This commit is contained in:
parent
3afe8b16a9
commit
da22f8a37c
@ -6,17 +6,46 @@
|
||||
#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();
|
||||
|
||||
void configure(ServoConfiguration servoConfig, ServerConfiguration serverConfig, EthernetConfiguration ethernetConfig, KeyConfiguration keyConfig);
|
||||
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;
|
||||
@ -26,7 +55,7 @@ private:
|
||||
|
||||
// An EthernetUDP instance to send and receive packets over UDP
|
||||
EthernetUDP udp;
|
||||
|
||||
EthernetHardwareStatus ethernetStatus;
|
||||
EthernetConfiguration ethernetConfig;
|
||||
bool ethernetIsConfigured = false;
|
||||
|
||||
@ -42,6 +71,31 @@ private:
|
||||
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;
|
||||
|
@ -46,14 +46,16 @@ class ServerConnection {
|
||||
|
||||
public:
|
||||
|
||||
ServerConnection();
|
||||
ServerConnection(ServerConfiguration configuration);
|
||||
|
||||
/**
|
||||
* @brief Set the configuration and the callback handler
|
||||
*
|
||||
* @param callback The handler to handle messages and errors
|
||||
*/
|
||||
void configure(ServerConfiguration configuration, ServerConnectionCallbacks* callbacks);
|
||||
void setCallbacks(ServerConnectionCallbacks* callbacks);
|
||||
|
||||
void shouldConnect(bool connect);
|
||||
|
||||
/**
|
||||
* @brief Call this function regularly to handle socket operations.
|
||||
@ -73,7 +75,8 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
uint32_t currentTime;
|
||||
uint32_t currentTime = 0;
|
||||
bool shouldBeConnected = false;
|
||||
|
||||
bool socketIsConnected() {
|
||||
return webSocket.isConnected();
|
||||
@ -81,15 +84,12 @@ private:
|
||||
|
||||
void connect();
|
||||
|
||||
void disconnect();
|
||||
|
||||
bool shouldReconnect = true;
|
||||
bool isConnecting = false;
|
||||
bool isDisconnecting = false;
|
||||
uint32_t connectionTimeout = 0;
|
||||
uint32_t nextReconnectAttemptMs = 0;
|
||||
|
||||
void didDisconnect();
|
||||
void didConnect();
|
||||
void didChangeConnectionState(bool isConnected);
|
||||
|
||||
|
||||
ServerConfiguration configuration;
|
||||
|
@ -52,15 +52,10 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Construct a new servo controller
|
||||
*/
|
||||
ServoController();
|
||||
|
||||
/**
|
||||
* @brief Configure the servo
|
||||
*
|
||||
* @param The configuration for the servo
|
||||
*/
|
||||
void configure(ServoConfiguration configuration);
|
||||
ServoController(ServoConfiguration configuration);
|
||||
|
||||
/**
|
||||
* @brief Update the servo state periodically
|
||||
|
@ -5,64 +5,135 @@
|
||||
#include <SPI.h>
|
||||
#include <Ethernet.h>
|
||||
|
||||
SesameController::SesameController() {
|
||||
|
||||
SesameController::SesameController(ServoConfiguration servoConfig, ServerConfiguration serverConfig, EthernetConfiguration ethernetConfig, KeyConfiguration keyConfig)
|
||||
: ethernetConfig(ethernetConfig), keyConfig(keyConfig), servo(servoConfig), server(serverConfig) {
|
||||
|
||||
}
|
||||
|
||||
void SesameController::configure(ServoConfiguration servoConfig, ServerConfiguration serverConfig, EthernetConfiguration ethernetConfig, KeyConfiguration keyConfig) {
|
||||
this->ethernetConfig = ethernetConfig;
|
||||
this->keyConfig = keyConfig;
|
||||
|
||||
// Ensure source of random numbers without WiFi and Bluetooth
|
||||
enableCrypto();
|
||||
|
||||
// Initialize SPI interface to Ethernet module
|
||||
void SesameController::initializeSpiBusForEthernetModule() {
|
||||
SPI.begin(ethernetConfig.spiPinSclk, ethernetConfig.spiPinMiso, ethernetConfig.spiPinMosi, ethernetConfig.spiPinSS); //SCLK, MISO, MOSI, SS
|
||||
pinMode(ethernetConfig.spiPinSS, OUTPUT);
|
||||
|
||||
Ethernet.init(ethernetConfig.spiPinSS);
|
||||
|
||||
if (Ethernet.begin(ethernetConfig.macAddress, ethernetConfig.dhcpLeaseTimeoutMs, ethernetConfig.dhcpLeaseResponseTimeoutMs) == 1) {
|
||||
Serial.print("[INFO] DHCP assigned IP ");
|
||||
Serial.println(Ethernet.localIP());
|
||||
ethernetIsConfigured = true;
|
||||
} else {
|
||||
// Check for Ethernet hardware present
|
||||
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
|
||||
Serial.println("[ERROR] Ethernet shield not found.");
|
||||
} else if (Ethernet.linkStatus() == LinkOFF) {
|
||||
Serial.println("[ERROR] Ethernet cable is not connected.");
|
||||
} else if (Ethernet.linkStatus() == Unknown) {
|
||||
Serial.println("[ERROR] Ethernet cable status unknown.");
|
||||
} else if (Ethernet.linkStatus() == LinkON) {
|
||||
Serial.println("[INFO] Ethernet cable is connected.");
|
||||
|
||||
// Try to configure using IP address instead of DHCP
|
||||
Ethernet.begin(ethernetConfig.macAddress, ethernetConfig.manualIp, ethernetConfig.manualDnsAddress);
|
||||
Serial.print("[WARNING] DHCP failed, using self-assigned IP ");
|
||||
Serial.println(Ethernet.localIP());
|
||||
ethernetIsConfigured = true;
|
||||
}
|
||||
}
|
||||
|
||||
servo.configure(servoConfig);
|
||||
Serial.println("[INFO] Servo configured");
|
||||
|
||||
// Direct messages and errors over the websocket to the controller
|
||||
server.configure(serverConfig, this);
|
||||
Serial.println("[INFO] Server connection configured");
|
||||
|
||||
udp.begin(ethernetConfig.udpPort);
|
||||
Serial.println("[INFO] Local UDP connection configured");
|
||||
}
|
||||
|
||||
void SesameController::loop(uint32_t millis) {
|
||||
currentTime = millis;
|
||||
//server.loop(millis);
|
||||
|
||||
checkLocalMessage();
|
||||
switch (status) {
|
||||
case SesameDeviceStatus::initial:
|
||||
// In initial state, first configure SPI and
|
||||
enableCrypto(); // Ensure source of random numbers without WiFi and Bluetooth
|
||||
initializeSpiBusForEthernetModule();
|
||||
// Direct messages and errors over the websocket to the controller
|
||||
server.setCallbacks(this);
|
||||
configureEthernet();
|
||||
status = SesameDeviceStatus::configuredButNoEthernetHardware;
|
||||
Serial.println("[INFO] State: initial -> noHardware");
|
||||
// Directly check for ethernet hardware
|
||||
// break;
|
||||
case SesameDeviceStatus::configuredButNoEthernetHardware:
|
||||
if (!hasAvailableEthernetHardware()) {
|
||||
// No ethernet hardware found, wait
|
||||
// TODO: Try rebooting after some time as a potential fix?
|
||||
break;
|
||||
}
|
||||
status = SesameDeviceStatus::ethernetHardwareButNoLink;
|
||||
Serial.println("[INFO] State: noHardware -> noLink");
|
||||
// Directly check for Ethernet link
|
||||
// break;
|
||||
case SesameDeviceStatus::ethernetHardwareButNoLink:
|
||||
if (!hasEthernetLink()) {
|
||||
if (!hasAvailableEthernetHardware()) {
|
||||
status = SesameDeviceStatus::configuredButNoEthernetHardware;
|
||||
Serial.println("[INFO] State: noLink -> noHardware");
|
||||
break;
|
||||
}
|
||||
// Wait for ethernet link
|
||||
// TODO: Try rebooting after some time as a potential fix?
|
||||
break;
|
||||
}
|
||||
status = SesameDeviceStatus::ethernetLinkButNoIP;
|
||||
Serial.println("[INFO] State: noLink -> noIP");
|
||||
// Directly check for socket connection
|
||||
// break;
|
||||
|
||||
case SesameDeviceStatus::ethernetLinkButNoIP:
|
||||
if (!hasEthernetLink()) {
|
||||
if (hasAvailableEthernetHardware()) {
|
||||
status = SesameDeviceStatus::ethernetHardwareButNoLink;
|
||||
Serial.println("[INFO] State: noIP -> noLink");
|
||||
} else {
|
||||
status = SesameDeviceStatus::configuredButNoEthernetHardware;
|
||||
Serial.println("[INFO] State: noIP -> noHardware");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
startUDP();
|
||||
status = SesameDeviceStatus::ipAddressButNoSocketConnection;
|
||||
Serial.println("[INFO] State: noIP -> noSocket");
|
||||
// Directly check for socket connection
|
||||
// break;
|
||||
|
||||
case SesameDeviceStatus::ipAddressButNoSocketConnection:
|
||||
if (!hasEthernetLink()) {
|
||||
server.shouldConnect(false);
|
||||
stopUDP();
|
||||
if (!hasAvailableEthernetHardware()) {
|
||||
status = SesameDeviceStatus::configuredButNoEthernetHardware;
|
||||
Serial.println("[INFO] State: noSocket -> noHardware");
|
||||
} else {
|
||||
status = SesameDeviceStatus::ethernetHardwareButNoLink;
|
||||
Serial.println("[INFO] State: noSocket -> noLink");
|
||||
}
|
||||
break;
|
||||
}
|
||||
server.shouldConnect(true);
|
||||
server.loop(millis);
|
||||
checkLocalMessage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool SesameController::hasAvailableEthernetHardware() {
|
||||
EthernetHardwareStatus ethernetStatus = Ethernet.hardwareStatus();
|
||||
|
||||
static bool didNotify = false;
|
||||
|
||||
if (ethernetStatus != EthernetW5500) {
|
||||
if (!didNotify) {
|
||||
Serial.print("[ERROR] No Ethernet hardware found: ");
|
||||
Serial.println(ethernetStatus);
|
||||
didNotify = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SesameController::hasEthernetLink() {
|
||||
return Ethernet.linkStatus() == EthernetLinkStatus::LinkON;
|
||||
}
|
||||
|
||||
void SesameController::configureEthernet() {
|
||||
if (Ethernet.begin(ethernetConfig.macAddress, ethernetConfig.dhcpLeaseTimeoutMs, ethernetConfig.dhcpLeaseResponseTimeoutMs) == 1) {
|
||||
Serial.print("[INFO] DHCP assigned IP ");
|
||||
Serial.println(Ethernet.localIP());
|
||||
return;
|
||||
}
|
||||
Ethernet.begin(ethernetConfig.macAddress, ethernetConfig.manualIp, ethernetConfig.manualDnsAddress);
|
||||
Serial.print("[WARNING] DHCP failed, using self-assigned IP ");
|
||||
Serial.println(Ethernet.localIP());
|
||||
}
|
||||
|
||||
void SesameController::startUDP() {
|
||||
udp.begin(ethernetConfig.udpPort);
|
||||
}
|
||||
|
||||
void SesameController::stopUDP() {
|
||||
udp.stop();
|
||||
}
|
||||
|
||||
// MARK: Local
|
||||
|
||||
void SesameController::checkLocalMessage() {
|
||||
|
82
src/main.cpp
82
src/main.cpp
@ -22,53 +22,51 @@
|
||||
#include "controller.h"
|
||||
#include "config.h"
|
||||
|
||||
SesameController controller{};
|
||||
ServoConfiguration servoConfig {
|
||||
.pwmTimer = pwmTimer,
|
||||
.pwmFrequency = servoFrequency,
|
||||
.pin = servoPin,
|
||||
.openDuration = lockOpeningDuration,
|
||||
.pressedValue = servoPressedState,
|
||||
.releasedValue = servoReleasedState,
|
||||
};
|
||||
|
||||
ServerConfiguration serverConfig {
|
||||
.url = serverUrl,
|
||||
.port = serverPort,
|
||||
.path = serverPath,
|
||||
.key = serverAccessKey,
|
||||
.reconnectTime = 5000,
|
||||
.socketHeartbeatIntervalMs = socketHeartbeatIntervalMs,
|
||||
.socketHeartbeatTimeoutMs = socketHeartbeatTimeoutMs,
|
||||
.socketHeartbeatFailureReconnectCount = socketHeartbeatFailureReconnectCount,
|
||||
};
|
||||
|
||||
EthernetConfiguration ethernetConfig {
|
||||
.macAddress = ethernetMacAddress,
|
||||
.spiPinMiso = spiPinMiso,
|
||||
.spiPinMosi = spiPinMosi,
|
||||
.spiPinSclk = spiPinSclk,
|
||||
.spiPinSS = spiPinSS,
|
||||
.dhcpLeaseTimeoutMs = dhcpLeaseTimeoutMs,
|
||||
.dhcpLeaseResponseTimeoutMs = dhcpLeaseResponseTimeoutMs,
|
||||
.manualIp = manualIpAddress,
|
||||
.manualDnsAddress = manualDnsServerAddress,
|
||||
.udpPort = localUdpPort,
|
||||
};
|
||||
|
||||
KeyConfiguration keyConfig {
|
||||
.remoteKey = remoteKey,
|
||||
.localKey = localKey,
|
||||
.challengeExpiryMs = challengeExpiryMs,
|
||||
};
|
||||
|
||||
SesameController controller(servoConfig, serverConfig, ethernetConfig, keyConfig);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(serialBaudRate);
|
||||
Serial.setDebugOutput(true);
|
||||
Serial.println("[INFO] Device started");
|
||||
|
||||
ServoConfiguration servoConfig {
|
||||
.pwmTimer = pwmTimer,
|
||||
.pwmFrequency = servoFrequency,
|
||||
.pin = servoPin,
|
||||
.openDuration = lockOpeningDuration,
|
||||
.pressedValue = servoPressedState,
|
||||
.releasedValue = servoReleasedState,
|
||||
};
|
||||
|
||||
ServerConfiguration serverConfig {
|
||||
.url = serverUrl,
|
||||
.port = serverPort,
|
||||
.path = serverPath,
|
||||
.key = serverAccessKey,
|
||||
.reconnectTime = 5000,
|
||||
.socketHeartbeatIntervalMs = socketHeartbeatIntervalMs,
|
||||
.socketHeartbeatTimeoutMs = socketHeartbeatTimeoutMs,
|
||||
.socketHeartbeatFailureReconnectCount = socketHeartbeatFailureReconnectCount,
|
||||
};
|
||||
|
||||
EthernetConfiguration ethernetConfig {
|
||||
.macAddress = ethernetMacAddress,
|
||||
.spiPinMiso = spiPinMiso,
|
||||
.spiPinMosi = spiPinMosi,
|
||||
.spiPinSclk = spiPinSclk,
|
||||
.spiPinSS = spiPinSS,
|
||||
.dhcpLeaseTimeoutMs = dhcpLeaseTimeoutMs,
|
||||
.dhcpLeaseResponseTimeoutMs = dhcpLeaseResponseTimeoutMs,
|
||||
.manualIp = manualIpAddress,
|
||||
.manualDnsAddress = manualDnsServerAddress,
|
||||
.udpPort = localUdpPort,
|
||||
};
|
||||
|
||||
KeyConfiguration keyConfig {
|
||||
.remoteKey = remoteKey,
|
||||
.localKey = localKey,
|
||||
.challengeExpiryMs = challengeExpiryMs,
|
||||
};
|
||||
|
||||
controller.configure(servoConfig, serverConfig, ethernetConfig, keyConfig);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
100
src/server.cpp
100
src/server.cpp
@ -1,26 +1,25 @@
|
||||
#include "server.h"
|
||||
|
||||
constexpr int32_t pingInterval = 10000;
|
||||
constexpr uint32_t pongTimeout = 5000;
|
||||
uint8_t disconnectTimeoutCount = 3;
|
||||
ServerConnection::ServerConnection(ServerConfiguration configuration) : configuration(configuration) { }
|
||||
|
||||
ServerConnection::ServerConnection() { }
|
||||
|
||||
void ServerConnection::configure(ServerConfiguration configuration, ServerConnectionCallbacks *callbacks) {
|
||||
void ServerConnection::setCallbacks(ServerConnectionCallbacks *callbacks) {
|
||||
controller = callbacks;
|
||||
this->configuration = configuration;
|
||||
}
|
||||
|
||||
void ServerConnection::connect() {
|
||||
if (webSocket.isConnected()) {
|
||||
void ServerConnection::shouldConnect(bool connect) {
|
||||
if (connect == shouldBeConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (controller == NULL) {
|
||||
Serial.println("[ERROR] No callbacks set for server");
|
||||
return;
|
||||
}
|
||||
shouldBeConnected = connect;
|
||||
nextReconnectAttemptMs = currentTime;
|
||||
}
|
||||
|
||||
isConnecting = true;
|
||||
void ServerConnection::connect() {
|
||||
Serial.printf("[INFO] Connecting to %s:%d%s\n", configuration.url, configuration.port, configuration.path);
|
||||
connectionTimeout = currentTime + configuration.socketHeartbeatIntervalMs;
|
||||
webSocket.begin(configuration.url, configuration.port, configuration.path);
|
||||
@ -33,47 +32,76 @@ void ServerConnection::connect() {
|
||||
webSocket.setReconnectInterval(configuration.reconnectTime);
|
||||
}
|
||||
|
||||
void ServerConnection::didDisconnect() {
|
||||
if (shouldReconnect || isConnecting) {
|
||||
return; // Disconnect already registered.
|
||||
void ServerConnection::didChangeConnectionState(bool isConnected) {
|
||||
static bool wasConnected = false;
|
||||
if (isConnected) {
|
||||
Serial.println("[INFO] Socket connected, enabling heartbeat");
|
||||
isConnecting = false;
|
||||
webSocket.enableHeartbeat(configuration.socketHeartbeatIntervalMs, configuration.socketHeartbeatTimeoutMs, configuration.socketHeartbeatFailureReconnectCount);
|
||||
} else {
|
||||
isDisconnecting = false;
|
||||
if (!wasConnected && shouldBeConnected && nextReconnectAttemptMs < currentTime) {
|
||||
nextReconnectAttemptMs = currentTime + configuration.socketHeartbeatIntervalMs;
|
||||
Serial.println("[INFO] Socket disconnected, setting reconnect time");
|
||||
} else if (wasConnected) {
|
||||
Serial.println("[INFO] Socket disconnected");
|
||||
}
|
||||
}
|
||||
Serial.println("[INFO] Socket disconnected");
|
||||
nextReconnectAttemptMs = currentTime + configuration.socketHeartbeatIntervalMs;
|
||||
shouldReconnect = true;
|
||||
}
|
||||
|
||||
void ServerConnection::didConnect() {
|
||||
isConnecting = false;
|
||||
Serial.println("[INFO] Socket connected");
|
||||
webSocket.enableHeartbeat(configuration.socketHeartbeatIntervalMs, configuration.socketHeartbeatTimeoutMs, configuration.socketHeartbeatFailureReconnectCount);
|
||||
}
|
||||
|
||||
void ServerConnection::disconnect() {
|
||||
webSocket.disconnect();
|
||||
wasConnected = isConnected;
|
||||
}
|
||||
|
||||
void ServerConnection::loop(uint32_t millis) {
|
||||
currentTime = millis;
|
||||
webSocket.loop();
|
||||
if (shouldReconnect && !isConnecting) {
|
||||
shouldReconnect = false;
|
||||
|
||||
if (shouldBeConnected) {
|
||||
if (isDisconnecting) {
|
||||
return; // Wait for disconnect to finish, then it will be reconnected
|
||||
}
|
||||
if (isConnecting) {
|
||||
if (millis > connectionTimeout) {
|
||||
// Cancel connection attempt
|
||||
Serial.println("[INFO] Canceling socket connection attempt");
|
||||
isDisconnecting = true;
|
||||
isConnecting = false;
|
||||
webSocket.disconnect();
|
||||
}
|
||||
return; // Wait for connect to finish
|
||||
}
|
||||
if (webSocket.isConnected()) {
|
||||
return; // Already connected
|
||||
}
|
||||
if (controller == NULL) {
|
||||
return;
|
||||
}
|
||||
if (millis < nextReconnectAttemptMs) {
|
||||
return; // Wait for next reconnect
|
||||
}
|
||||
isConnecting = true;
|
||||
connect();
|
||||
}
|
||||
if (isConnecting && millis > connectionTimeout) {
|
||||
Serial.println("[INFO] Failed to connect");
|
||||
disconnect();
|
||||
shouldReconnect = true;
|
||||
isConnecting = false;
|
||||
} else {
|
||||
if (isDisconnecting) {
|
||||
return; // Wait for disconnect
|
||||
}
|
||||
if (isConnecting) {
|
||||
return; // Wait until connection is established, then it will be disconnected
|
||||
}
|
||||
if (!webSocket.isConnected()) {
|
||||
return;
|
||||
}
|
||||
isDisconnecting = true;
|
||||
Serial.println("[INFO] Disconnecting socket");
|
||||
webSocket.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConnection::webSocketEventHandler(WStype_t type, uint8_t * payload, size_t length) {
|
||||
switch(type) {
|
||||
case WStype_DISCONNECTED:
|
||||
didDisconnect();
|
||||
didChangeConnectionState(false);
|
||||
break;
|
||||
case WStype_CONNECTED:
|
||||
didConnect();
|
||||
didChangeConnectionState(true);
|
||||
break;
|
||||
case WStype_TEXT:
|
||||
controller->sendServerError(MessageResult::TextReceivedOverSocket);
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
#include <esp32-hal.h> // For `millis()`
|
||||
|
||||
ServoController::ServoController() { }
|
||||
|
||||
void performReset(void * pvParameters) {
|
||||
ServoController* servo = (ServoController *) pvParameters;
|
||||
for(;;){
|
||||
@ -12,7 +10,7 @@ void performReset(void * pvParameters) {
|
||||
}
|
||||
}
|
||||
|
||||
void ServoController::configure(ServoConfiguration configuration) {
|
||||
ServoController::ServoController(ServoConfiguration configuration) {
|
||||
|
||||
// Create a task that runs on a different core,
|
||||
// So that it's always executed
|
||||
|
Loading…
Reference in New Issue
Block a user