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:
244
src/BLE_Interface.cpp
Normal file
244
src/BLE_Interface.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
#include "EggDuino.h"
|
||||
|
||||
#ifdef ESP32
|
||||
#include <NimBLEDevice.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr char kBleDeviceNamePrefix[] = "EggDuino_";
|
||||
constexpr char kBleServiceUuid[] = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";
|
||||
constexpr char kBleRxCharUuid[] = "6e400002-b5a3-f393-e0a9-e50e24dcca9e";
|
||||
constexpr char kBleTxCharUuid[] = "6e400003-b5a3-f393-e0a9-e50e24dcca9e";
|
||||
|
||||
constexpr size_t kBleRxQueueSize = 512;
|
||||
constexpr size_t kBleNotifyChunkSize = 20;
|
||||
|
||||
NimBLEServer *g_pBleServer = NULL;
|
||||
NimBLECharacteristic *g_pBleTxCharacteristic = NULL;
|
||||
|
||||
uint8_t g_bleRxQueue[kBleRxQueueSize];
|
||||
size_t g_bleRxHead = 0;
|
||||
size_t g_bleRxTail = 0;
|
||||
bool g_bleRxQueueOverflow = false;
|
||||
bool g_bleClientConnected = false;
|
||||
|
||||
portMUX_TYPE g_bleQueueMux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
void logBleDiag(const String &message)
|
||||
{
|
||||
Log(message);
|
||||
Serial.println(message);
|
||||
}
|
||||
|
||||
void buildBleDeviceName(char *nameBuffer, size_t bufferSize)
|
||||
{
|
||||
if ((nameBuffer == NULL) || (bufferSize == 0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Tasmota-style chip ID uses the lower 24 bits of the ESP32 efuse MAC.
|
||||
const uint32_t chipId = static_cast<uint32_t>(ESP.getEfuseMac() & 0xFFFFFFULL);
|
||||
snprintf(nameBuffer, bufferSize, "%s%06X", kBleDeviceNamePrefix, chipId);
|
||||
}
|
||||
|
||||
bool queueBleByte(uint8_t value)
|
||||
{
|
||||
bool queued = false;
|
||||
portENTER_CRITICAL(&g_bleQueueMux);
|
||||
const size_t nextHead = (g_bleRxHead + 1) % kBleRxQueueSize;
|
||||
if (nextHead == g_bleRxTail)
|
||||
{
|
||||
g_bleRxQueueOverflow = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_bleRxQueue[g_bleRxHead] = value;
|
||||
g_bleRxHead = nextHead;
|
||||
queued = true;
|
||||
}
|
||||
portEXIT_CRITICAL(&g_bleQueueMux);
|
||||
return queued;
|
||||
}
|
||||
|
||||
bool dequeueBleByte(uint8_t *value)
|
||||
{
|
||||
bool hasData = false;
|
||||
portENTER_CRITICAL(&g_bleQueueMux);
|
||||
if (g_bleRxHead != g_bleRxTail)
|
||||
{
|
||||
*value = g_bleRxQueue[g_bleRxTail];
|
||||
g_bleRxTail = (g_bleRxTail + 1) % kBleRxQueueSize;
|
||||
hasData = true;
|
||||
}
|
||||
portEXIT_CRITICAL(&g_bleQueueMux);
|
||||
return hasData;
|
||||
}
|
||||
|
||||
class EggDuinoBleServerCallbacks : public NimBLEServerCallbacks
|
||||
{
|
||||
void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo)
|
||||
{
|
||||
(void)pServer;
|
||||
(void)connInfo;
|
||||
g_bleClientConnected = true;
|
||||
Log("BLE client connected");
|
||||
}
|
||||
|
||||
void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason)
|
||||
{
|
||||
(void)connInfo;
|
||||
(void)reason;
|
||||
g_bleClientConnected = false;
|
||||
const bool restartedAdvertising = pServer->startAdvertising();
|
||||
logBleDiag(String("BLE client disconnected; advertising restart: ") + (restartedAdvertising ? "ok" : "failed"));
|
||||
}
|
||||
};
|
||||
|
||||
class EggDuinoBleRxCallbacks : public NimBLECharacteristicCallbacks
|
||||
{
|
||||
void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo)
|
||||
{
|
||||
(void)connInfo;
|
||||
const std::string value = pCharacteristic->getValue();
|
||||
for (size_t i = 0; i < value.size(); ++i)
|
||||
{
|
||||
queueBleByte(static_cast<uint8_t>(value[i]));
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
void startBleInterface()
|
||||
{
|
||||
char bleDeviceName[32] = {0};
|
||||
buildBleDeviceName(bleDeviceName, sizeof(bleDeviceName));
|
||||
if (bleDeviceName[0] == '\0')
|
||||
{
|
||||
snprintf(bleDeviceName, sizeof(bleDeviceName), "%sUNKNOWN", kBleDeviceNamePrefix);
|
||||
}
|
||||
|
||||
logBleDiag("BLE init begin");
|
||||
logBleDiag(String("BLE device name: ") + bleDeviceName);
|
||||
logBleDiag(String("BLE service UUID: ") + kBleServiceUuid);
|
||||
logBleDiag(String("BLE RX UUID: ") + kBleRxCharUuid);
|
||||
logBleDiag(String("BLE TX UUID: ") + kBleTxCharUuid);
|
||||
|
||||
NimBLEDevice::init(bleDeviceName);
|
||||
const bool blePowerSet = NimBLEDevice::setPower(ESP_PWR_LVL_P6);
|
||||
const std::string bleAddress = NimBLEDevice::getAddress().toString();
|
||||
logBleDiag(String("BLE radio address: ") + bleAddress.c_str());
|
||||
logBleDiag(String("BLE TX power set: ") + (blePowerSet ? "ok" : "failed"));
|
||||
|
||||
g_pBleServer = NimBLEDevice::createServer();
|
||||
if (g_pBleServer == NULL)
|
||||
{
|
||||
logBleDiag("BLE init failed: createServer returned null");
|
||||
return;
|
||||
}
|
||||
g_pBleServer->setCallbacks(new EggDuinoBleServerCallbacks());
|
||||
logBleDiag("BLE server created");
|
||||
|
||||
NimBLEService *pService = g_pBleServer->createService(kBleServiceUuid);
|
||||
if (pService == NULL)
|
||||
{
|
||||
logBleDiag("BLE init failed: createService returned null");
|
||||
return;
|
||||
}
|
||||
g_pBleTxCharacteristic = pService->createCharacteristic(
|
||||
kBleTxCharUuid,
|
||||
NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ);
|
||||
if (g_pBleTxCharacteristic == NULL)
|
||||
{
|
||||
logBleDiag("BLE init failed: TX characteristic creation failed");
|
||||
return;
|
||||
}
|
||||
|
||||
NimBLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
|
||||
kBleRxCharUuid,
|
||||
NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR);
|
||||
if (pRxCharacteristic == NULL)
|
||||
{
|
||||
logBleDiag("BLE init failed: RX characteristic creation failed");
|
||||
return;
|
||||
}
|
||||
pRxCharacteristic->setCallbacks(new EggDuinoBleRxCallbacks());
|
||||
logBleDiag("BLE characteristics created");
|
||||
|
||||
const bool serviceStarted = pService->start();
|
||||
logBleDiag(String("BLE service start: ") + (serviceStarted ? "ok" : "failed"));
|
||||
if (!serviceStarted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
if (pAdvertising == NULL)
|
||||
{
|
||||
logBleDiag("BLE init failed: getAdvertising returned null");
|
||||
return;
|
||||
}
|
||||
pAdvertising->enableScanResponse(true);
|
||||
const bool localNameSet = pAdvertising->setName(bleDeviceName);
|
||||
const bool serviceUuidAdded = pAdvertising->addServiceUUID(kBleServiceUuid);
|
||||
const bool advertisingStarted = pAdvertising->start();
|
||||
logBleDiag(String("BLE advertising set local name: ") + (localNameSet ? "ok" : "failed"));
|
||||
logBleDiag(String("BLE advertising add service UUID: ") + (serviceUuidAdded ? "ok" : "failed"));
|
||||
logBleDiag(String("BLE advertising start: ") + (advertisingStarted ? "ok" : "failed"));
|
||||
if (serviceUuidAdded && advertisingStarted)
|
||||
{
|
||||
logBleDiag("BLE service started");
|
||||
}
|
||||
}
|
||||
|
||||
void handleBleInterface()
|
||||
{
|
||||
if (g_bleRxQueueOverflow)
|
||||
{
|
||||
g_bleRxQueueOverflow = false;
|
||||
Log("BLE RX queue overflow");
|
||||
}
|
||||
|
||||
uint8_t value = 0;
|
||||
while (dequeueBleByte(&value))
|
||||
{
|
||||
setActiveProtocolContext(&g_BLECmd, PROTOCOL_TRANSPORT_BLE);
|
||||
g_BLECmd.readChar(static_cast<char>(value));
|
||||
}
|
||||
}
|
||||
|
||||
bool bleProtocolWrite(const char *message)
|
||||
{
|
||||
if ((message == NULL) || !g_bleClientConnected || (g_pBleTxCharacteristic == NULL))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint8_t *payload = reinterpret_cast<const uint8_t *>(message);
|
||||
size_t remaining = strlen(message);
|
||||
if (remaining == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
while (remaining > 0)
|
||||
{
|
||||
size_t chunkLen = remaining;
|
||||
if (chunkLen > kBleNotifyChunkSize)
|
||||
{
|
||||
chunkLen = kBleNotifyChunkSize;
|
||||
}
|
||||
|
||||
g_pBleTxCharacteristic->setValue(payload, chunkLen);
|
||||
g_pBleTxCharacteristic->notify();
|
||||
|
||||
payload += chunkLen;
|
||||
remaining -= chunkLen;
|
||||
delay(3);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -397,6 +397,7 @@ void startWebInterface()
|
||||
server.on("/api/logs", HTTP_GET, handleGetLogs);
|
||||
server.onNotFound(handleNotFound);
|
||||
server.begin();
|
||||
startWifiProtocolInterface();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -8,13 +8,13 @@ void queryPen()
|
||||
state = '1';
|
||||
else
|
||||
state = '0';
|
||||
Serial.print(String(state) + "\r\n");
|
||||
protocolWrite(String(state) + "\r\n");
|
||||
sendAck();
|
||||
}
|
||||
|
||||
void queryButton()
|
||||
{
|
||||
Serial.print(String(g_bPrgButtonState) + "\r\n");
|
||||
protocolWrite(String(g_bPrgButtonState) + "\r\n");
|
||||
sendAck();
|
||||
g_bPrgButtonState = 0;
|
||||
}
|
||||
@@ -22,7 +22,7 @@ void queryButton()
|
||||
void queryLayer()
|
||||
{
|
||||
Log(__FUNCTION__);
|
||||
Serial.print(String(g_uiLayer) + "\r\n");
|
||||
protocolWrite(String(g_uiLayer) + "\r\n");
|
||||
sendAck();
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ void setLayer()
|
||||
Log(__FUNCTION__);
|
||||
uint32_t value = 0;
|
||||
char *arg1;
|
||||
arg1 = SCmd.next();
|
||||
arg1 = nextCommandArg();
|
||||
if (arg1 != NULL)
|
||||
{
|
||||
value = atoi(arg1);
|
||||
@@ -44,7 +44,7 @@ void setLayer()
|
||||
|
||||
void queryNodeCount()
|
||||
{
|
||||
Serial.print(String(g_uiNodeCount) + "\r\n");
|
||||
protocolWrite(String(g_uiNodeCount) + "\r\n");
|
||||
sendAck();
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ void setNodeCount()
|
||||
Log(__FUNCTION__);
|
||||
uint32_t value = 0;
|
||||
char *arg1;
|
||||
arg1 = SCmd.next();
|
||||
arg1 = nextCommandArg();
|
||||
if (arg1 != NULL)
|
||||
{
|
||||
value = atoi(arg1);
|
||||
@@ -112,7 +112,7 @@ void setPen()
|
||||
|
||||
moveToDestination();
|
||||
|
||||
arg = SCmd.next();
|
||||
arg = nextCommandArg();
|
||||
if (arg != NULL)
|
||||
{
|
||||
cmd = atoi(arg);
|
||||
@@ -131,7 +131,7 @@ void setPen()
|
||||
}
|
||||
}
|
||||
char *val;
|
||||
val = SCmd.next();
|
||||
val = nextCommandArg();
|
||||
if (val != NULL)
|
||||
{
|
||||
value = atoi(val);
|
||||
@@ -156,7 +156,7 @@ void togglePen()
|
||||
|
||||
moveToDestination();
|
||||
|
||||
arg = SCmd.next();
|
||||
arg = nextCommandArg();
|
||||
if (arg != NULL)
|
||||
value = atoi(arg);
|
||||
else
|
||||
@@ -189,10 +189,10 @@ void enableMotors()
|
||||
int value;
|
||||
char *arg;
|
||||
char *val;
|
||||
arg = SCmd.next();
|
||||
arg = nextCommandArg();
|
||||
if (arg != NULL)
|
||||
cmd = atoi(arg);
|
||||
val = SCmd.next();
|
||||
val = nextCommandArg();
|
||||
if (val != NULL)
|
||||
value = atoi(val);
|
||||
// values parsed
|
||||
@@ -237,11 +237,11 @@ void stepperModeConfigure()
|
||||
int cmd;
|
||||
int value;
|
||||
char *arg;
|
||||
arg = SCmd.next();
|
||||
arg = nextCommandArg();
|
||||
if (arg != NULL)
|
||||
cmd = atoi(arg);
|
||||
char *val;
|
||||
val = SCmd.next();
|
||||
val = nextCommandArg();
|
||||
if (val != NULL)
|
||||
value = atoi(val);
|
||||
if ((arg != NULL) && (val != NULL))
|
||||
@@ -281,8 +281,8 @@ void stepperModeConfigure()
|
||||
void sendVersion()
|
||||
{
|
||||
Log(__FUNCTION__);
|
||||
Serial.print(initSting);
|
||||
Serial.print("\r\n");
|
||||
protocolWrite(initSting);
|
||||
protocolWrite("\r\n");
|
||||
}
|
||||
|
||||
void unrecognized(const char *command)
|
||||
@@ -299,21 +299,29 @@ void ignore()
|
||||
|
||||
void makeComInterface()
|
||||
{
|
||||
SCmd.addCommand("v", sendVersion);
|
||||
SCmd.addCommand("EM", enableMotors);
|
||||
SCmd.addCommand("SC", stepperModeConfigure);
|
||||
SCmd.addCommand("SP", setPen);
|
||||
SCmd.addCommand("SM", stepperMove);
|
||||
SCmd.addCommand("SE", ignore);
|
||||
SCmd.addCommand("TP", togglePen);
|
||||
SCmd.addCommand("PO", ignore); // Engraver command, not implemented, gives fake answer
|
||||
SCmd.addCommand("NI", nodeCountIncrement);
|
||||
SCmd.addCommand("ND", nodeCountDecrement);
|
||||
SCmd.addCommand("SN", setNodeCount);
|
||||
SCmd.addCommand("QN", queryNodeCount);
|
||||
SCmd.addCommand("SL", setLayer);
|
||||
SCmd.addCommand("QL", queryLayer);
|
||||
SCmd.addCommand("QP", queryPen);
|
||||
SCmd.addCommand("QB", queryButton); //"PRG" Button,
|
||||
SCmd.setDefaultHandler(unrecognized); // Handler for command that isn't matched (says "What?")
|
||||
auto registerCommands = [](SerialCommand &cmd) {
|
||||
cmd.addCommand("v", sendVersion);
|
||||
cmd.addCommand("EM", enableMotors);
|
||||
cmd.addCommand("SC", stepperModeConfigure);
|
||||
cmd.addCommand("SP", setPen);
|
||||
cmd.addCommand("SM", stepperMove);
|
||||
cmd.addCommand("SE", ignore);
|
||||
cmd.addCommand("TP", togglePen);
|
||||
cmd.addCommand("PO", ignore); // Engraver command, not implemented, gives fake answer
|
||||
cmd.addCommand("NI", nodeCountIncrement);
|
||||
cmd.addCommand("ND", nodeCountDecrement);
|
||||
cmd.addCommand("SN", setNodeCount);
|
||||
cmd.addCommand("QN", queryNodeCount);
|
||||
cmd.addCommand("SL", setLayer);
|
||||
cmd.addCommand("QL", queryLayer);
|
||||
cmd.addCommand("QP", queryPen);
|
||||
cmd.addCommand("QB", queryButton); //"PRG" Button,
|
||||
cmd.setDefaultHandler(unrecognized); // Handler for command that isn't matched (says "What?")
|
||||
};
|
||||
|
||||
registerCommands(SCmd);
|
||||
#ifdef ESP32
|
||||
registerCommands(g_BLECmd);
|
||||
registerCommands(g_WifiCmd);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -52,13 +52,13 @@ void storePenDownPosInEE()
|
||||
void sendAck()
|
||||
{
|
||||
Log(__FUNCTION__);
|
||||
Serial.print("OK\r\n");
|
||||
protocolWrite("OK\r\n");
|
||||
}
|
||||
|
||||
void sendError()
|
||||
{
|
||||
Log(__FUNCTION__);
|
||||
Serial.print("unknown CMD\r\n");
|
||||
protocolWrite("unknown CMD\r\n");
|
||||
}
|
||||
|
||||
void motorsOff()
|
||||
@@ -92,19 +92,19 @@ void toggleMotors()
|
||||
|
||||
bool parseSMArgs(uint16_t *duration, int *penStepsEBB, int *rotStepsEBB)
|
||||
{
|
||||
char *arg1;
|
||||
char *arg2;
|
||||
char *arg3;
|
||||
arg1 = SCmd.next();
|
||||
char *arg1 = NULL;
|
||||
char *arg2 = NULL;
|
||||
char *arg3 = NULL;
|
||||
arg1 = nextCommandArg();
|
||||
if (arg1 != NULL)
|
||||
{
|
||||
*duration = atoi(arg1);
|
||||
arg2 = SCmd.next();
|
||||
arg2 = nextCommandArg();
|
||||
}
|
||||
if (arg2 != NULL)
|
||||
{
|
||||
*penStepsEBB = atoi(arg2);
|
||||
arg3 = SCmd.next();
|
||||
arg3 = nextCommandArg();
|
||||
}
|
||||
if (arg3 != NULL)
|
||||
{
|
||||
|
||||
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
|
||||
60
src/main.cpp
60
src/main.cpp
@@ -36,6 +36,16 @@ FastAccelStepper *g_pStepperPen = NULL;
|
||||
// make Objects
|
||||
Servo penServo;
|
||||
SerialCommand SCmd;
|
||||
#ifdef ESP32
|
||||
SerialCommand g_BLECmd;
|
||||
SerialCommand g_WifiCmd;
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
SerialCommand *g_pActiveParser = &SCmd;
|
||||
ProtocolTransport g_activeTransport = PROTOCOL_TRANSPORT_SERIAL;
|
||||
}
|
||||
|
||||
// create Buttons
|
||||
#ifdef prgButton
|
||||
@@ -63,6 +73,52 @@ float fROT_STEP_CORRECTION = 16.0 / rotMicrostep; // devide EBB-Coordinates by t
|
||||
float fPEN_STEP_CORRECTION = 16.0 / penMicrostep; // devide EBB-Coordinates by this factor to get EGGduino-Steps
|
||||
boolean g_bMotorsEnabled = 0;
|
||||
|
||||
void setActiveProtocolContext(SerialCommand *parser, ProtocolTransport transport)
|
||||
{
|
||||
if (parser != NULL)
|
||||
{
|
||||
g_pActiveParser = parser;
|
||||
}
|
||||
g_activeTransport = transport;
|
||||
}
|
||||
|
||||
char *nextCommandArg()
|
||||
{
|
||||
return g_pActiveParser->next();
|
||||
}
|
||||
|
||||
void protocolWrite(const char *message)
|
||||
{
|
||||
if (message == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ESP32
|
||||
if (g_activeTransport == PROTOCOL_TRANSPORT_BLE)
|
||||
{
|
||||
if (bleProtocolWrite(message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (g_activeTransport == PROTOCOL_TRANSPORT_WIFI)
|
||||
{
|
||||
if (wifiProtocolWrite(message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Serial.print(message);
|
||||
}
|
||||
|
||||
void protocolWrite(const String &message)
|
||||
{
|
||||
protocolWrite(message.c_str());
|
||||
}
|
||||
|
||||
// Stepper Test
|
||||
#ifdef TEST
|
||||
// #define dirPinStepper 16
|
||||
@@ -77,6 +133,7 @@ void setup()
|
||||
Log("Starting...");
|
||||
makeComInterface();
|
||||
initHardware();
|
||||
startBleInterface();
|
||||
startWebInterface();
|
||||
}
|
||||
|
||||
@@ -134,8 +191,11 @@ void loop()
|
||||
}
|
||||
#else
|
||||
// moveOneStep();
|
||||
setActiveProtocolContext(&SCmd, PROTOCOL_TRANSPORT_SERIAL);
|
||||
SCmd.readSerial();
|
||||
handleBleInterface();
|
||||
handleWebInterface();
|
||||
handleWifiProtocolInterface();
|
||||
#endif
|
||||
|
||||
#ifdef penToggleButton
|
||||
|
||||
Reference in New Issue
Block a user