Refactor SerialCommand to support Stream interface and improve command handling
- Added readSerial(Stream &stream) method to allow reading from any Stream-compatible transport. - Introduced readChar(char inChar) method for processing individual characters. - Updated command matching logic to enhance debugging output. - Improved buffer handling and command execution flow. Enhance platformio.ini for better compatibility and added libraries - Added NimBLE-Arduino and WebSockets libraries for BLE and WiFi support. - Updated upload and monitor ports for better compatibility with macOS. Integrate WiFi and BLE protocol interfaces - Implemented startWebInterface() to initialize WiFi protocol alongside existing web server. - Added BLE support with a new EggBot BLE Serial Protocol for command handling over BLE. - Created WebSocket server for WiFi communication, maintaining compatibility with existing command protocols. Refactor command handling in Functions.cpp - Replaced direct Serial.print calls with protocolWrite for consistent output handling. - Updated command registration to use a lambda function for better readability and maintainability. Add documentation for EggBot protocols - Created separate markdown files for BLE, WiFi, and Serial protocols detailing command structures and usage. - Provided examples of command transactions for better developer guidance. Implement BLE and WiFi protocol handling in respective source files - Developed BLE_Interface.cpp for managing BLE connections and data transmission. - Created WiFi_Protocol.cpp for handling WebSocket communication and data reception.
This commit is contained in:
156
src/WiFi_Protocol.cpp
Normal file
156
src/WiFi_Protocol.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "EggDuino.h"
|
||||
|
||||
#ifdef ESP32
|
||||
#include <WebSocketsServer.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr uint16_t kWifiProtocolPort = 1337;
|
||||
constexpr uint8_t kInvalidWifiClientId = 0xFF;
|
||||
constexpr size_t kWifiRxQueueSize = 1024;
|
||||
|
||||
struct WifiRxByte
|
||||
{
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
WebSocketsServer g_wifiProtocolSocket(kWifiProtocolPort);
|
||||
WifiRxByte g_wifiRxQueue[kWifiRxQueueSize];
|
||||
size_t g_wifiRxHead = 0;
|
||||
size_t g_wifiRxTail = 0;
|
||||
bool g_wifiRxOverflow = false;
|
||||
bool g_wifiProtocolStarted = false;
|
||||
uint8_t g_wifiProtocolClientId = kInvalidWifiClientId;
|
||||
|
||||
bool queueWifiByte(uint8_t value)
|
||||
{
|
||||
const size_t nextHead = (g_wifiRxHead + 1) % kWifiRxQueueSize;
|
||||
if (nextHead == g_wifiRxTail)
|
||||
{
|
||||
g_wifiRxOverflow = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
g_wifiRxQueue[g_wifiRxHead].value = value;
|
||||
g_wifiRxHead = nextHead;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dequeueWifiByte(WifiRxByte *byte)
|
||||
{
|
||||
if ((byte == NULL) || (g_wifiRxHead == g_wifiRxTail))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*byte = g_wifiRxQueue[g_wifiRxTail];
|
||||
g_wifiRxTail = (g_wifiRxTail + 1) % kWifiRxQueueSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
void handleWifiSocketEvent(uint8_t clientId, WStype_t type, uint8_t *payload, size_t length)
|
||||
{
|
||||
(void)payload;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case WStype_CONNECTED:
|
||||
if (g_wifiProtocolClientId == kInvalidWifiClientId)
|
||||
{
|
||||
g_wifiProtocolClientId = clientId;
|
||||
}
|
||||
Log(String("WiFi protocol client connected: ") + clientId);
|
||||
break;
|
||||
|
||||
case WStype_DISCONNECTED:
|
||||
if (g_wifiProtocolClientId == clientId)
|
||||
{
|
||||
g_wifiProtocolClientId = kInvalidWifiClientId;
|
||||
}
|
||||
Log(String("WiFi protocol client disconnected: ") + clientId);
|
||||
break;
|
||||
|
||||
case WStype_TEXT:
|
||||
case WStype_BIN:
|
||||
if (g_wifiProtocolClientId == kInvalidWifiClientId)
|
||||
{
|
||||
g_wifiProtocolClientId = clientId;
|
||||
}
|
||||
if (clientId != g_wifiProtocolClientId)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
{
|
||||
queueWifiByte(payload[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void startWifiProtocolInterface()
|
||||
{
|
||||
if (g_wifiProtocolStarted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_wifiProtocolSocket.begin();
|
||||
g_wifiProtocolSocket.onEvent(handleWifiSocketEvent);
|
||||
g_wifiProtocolStarted = true;
|
||||
|
||||
Log(String("WiFi EggBot protocol ws://") + WiFi.localIP().toString() + ":" + kWifiProtocolPort);
|
||||
}
|
||||
|
||||
void handleWifiProtocolInterface()
|
||||
{
|
||||
if (!g_wifiProtocolStarted)
|
||||
{
|
||||
if (WiFi.status() == WL_CONNECTED)
|
||||
{
|
||||
startWifiProtocolInterface();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
g_wifiProtocolSocket.loop();
|
||||
|
||||
if (g_wifiRxOverflow)
|
||||
{
|
||||
g_wifiRxOverflow = false;
|
||||
Log("WiFi protocol RX queue overflow");
|
||||
}
|
||||
|
||||
WifiRxByte byte = {0};
|
||||
while (dequeueWifiByte(&byte))
|
||||
{
|
||||
setActiveProtocolContext(&g_WifiCmd, PROTOCOL_TRANSPORT_WIFI);
|
||||
g_WifiCmd.readChar(static_cast<char>(byte.value));
|
||||
}
|
||||
}
|
||||
|
||||
bool wifiProtocolWrite(const char *message)
|
||||
{
|
||||
if (!g_wifiProtocolStarted || (message == NULL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((g_wifiProtocolClientId == kInvalidWifiClientId) || !g_wifiProtocolSocket.clientIsConnected(g_wifiProtocolClientId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return g_wifiProtocolSocket.sendTXT(g_wifiProtocolClientId, message);
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user