#include "EggDuino.h" #ifdef ESP32 #include 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(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