Files
EggDuino/src/WiFi_Protocol.cpp
André Fiedler a1ffcb08ca 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.
2026-02-24 22:00:26 +01:00

157 lines
3.0 KiB
C++

#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