2025-03-03 13:26:37 +01:00
|
|
|
#include "SerialWifiInterface.h"
|
|
|
|
|
#include <WiFi.h>
|
|
|
|
|
|
|
|
|
|
void SerialWifiInterface::begin(int port) {
|
|
|
|
|
// wifi setup is handled outside of this class, only starts the server
|
|
|
|
|
server.begin(port);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------- public methods
|
|
|
|
|
void SerialWifiInterface::enable() {
|
|
|
|
|
if (_isEnabled) return;
|
|
|
|
|
|
|
|
|
|
_isEnabled = true;
|
|
|
|
|
clearBuffers();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SerialWifiInterface::disable() {
|
|
|
|
|
_isEnabled = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t SerialWifiInterface::writeFrame(const uint8_t src[], size_t len) {
|
|
|
|
|
if (len > MAX_FRAME_SIZE) {
|
2025-03-04 14:04:47 +11:00
|
|
|
WIFI_DEBUG_PRINTLN("writeFrame(), frame too big, len=%d\n", len);
|
2025-03-03 13:26:37 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (deviceConnected && len > 0) {
|
|
|
|
|
if (send_queue_len >= FRAME_QUEUE_SIZE) {
|
2025-03-04 14:04:47 +11:00
|
|
|
WIFI_DEBUG_PRINTLN("writeFrame(), send_queue is full!");
|
2025-03-03 13:26:37 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
send_queue[send_queue_len].len = len; // add to send queue
|
|
|
|
|
memcpy(send_queue[send_queue_len].buf, src, len);
|
|
|
|
|
send_queue_len++;
|
|
|
|
|
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SerialWifiInterface::isWriteBusy() const {
|
2025-03-04 14:04:47 +11:00
|
|
|
return false;
|
2025-03-03 13:26:37 +01:00
|
|
|
}
|
|
|
|
|
|
2026-01-03 16:36:19 +13:00
|
|
|
bool SerialWifiInterface::hasReceivedFrameHeader() {
|
|
|
|
|
return received_frame_header.type != 0 && received_frame_header.length != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SerialWifiInterface::resetReceivedFrameHeader() {
|
|
|
|
|
received_frame_header.type = 0;
|
|
|
|
|
received_frame_header.length = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-03 13:26:37 +01:00
|
|
|
size_t SerialWifiInterface::checkRecvFrame(uint8_t dest[]) {
|
2026-04-12 20:23:42 -07:00
|
|
|
// periodic WiFi health check (every 60s, only after first successful connection)
|
|
|
|
|
if (WiFi.status() == WL_CONNECTED) {
|
|
|
|
|
_wifi_was_connected = true;
|
|
|
|
|
} else if (_wifi_was_connected && millis() >= _wifi_check_time) {
|
|
|
|
|
WIFI_DEBUG_PRINTLN("WiFi disconnected, attempting reconnect...");
|
|
|
|
|
WiFi.reconnect();
|
|
|
|
|
_wifi_check_time = millis() + 60000;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-29 19:47:24 +12:00
|
|
|
// check if new client connected
|
|
|
|
|
auto newClient = server.available();
|
|
|
|
|
if (newClient) {
|
|
|
|
|
|
|
|
|
|
// disconnect existing client
|
|
|
|
|
deviceConnected = false;
|
|
|
|
|
client.stop();
|
|
|
|
|
|
|
|
|
|
// switch active connection to new client
|
|
|
|
|
client = newClient;
|
2026-01-03 15:39:57 +13:00
|
|
|
|
|
|
|
|
// forget received frame header
|
2026-01-03 16:36:19 +13:00
|
|
|
resetReceivedFrameHeader();
|
2025-08-29 19:47:24 +12:00
|
|
|
|
|
|
|
|
}
|
2025-03-03 13:26:37 +01:00
|
|
|
|
|
|
|
|
if (client.connected()) {
|
|
|
|
|
if (!deviceConnected) {
|
2025-03-04 14:04:47 +11:00
|
|
|
WIFI_DEBUG_PRINTLN("Got connection");
|
2025-03-03 13:26:37 +01:00
|
|
|
deviceConnected = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (deviceConnected) {
|
|
|
|
|
deviceConnected = false;
|
2025-03-04 14:04:47 +11:00
|
|
|
WIFI_DEBUG_PRINTLN("Disconnected");
|
2025-03-03 13:26:37 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (deviceConnected) {
|
|
|
|
|
if (send_queue_len > 0) { // first, check send queue
|
|
|
|
|
|
|
|
|
|
_last_write = millis();
|
|
|
|
|
int len = send_queue[0].len;
|
|
|
|
|
|
|
|
|
|
uint8_t pkt[3+len]; // use same header as serial interface so client can delimit frames
|
|
|
|
|
pkt[0] = '>';
|
|
|
|
|
pkt[1] = (len & 0xFF); // LSB
|
|
|
|
|
pkt[2] = (len >> 8); // MSB
|
|
|
|
|
memcpy(&pkt[3], send_queue[0].buf, send_queue[0].len);
|
|
|
|
|
client.write(pkt, 3 + len);
|
|
|
|
|
send_queue_len--;
|
|
|
|
|
for (int i = 0; i < send_queue_len; i++) { // delete top item from queue
|
|
|
|
|
send_queue[i] = send_queue[i + 1];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2026-01-03 15:39:57 +13:00
|
|
|
|
|
|
|
|
// check if we are waiting for a frame header
|
2026-01-03 16:36:19 +13:00
|
|
|
if(!hasReceivedFrameHeader()){
|
2026-01-03 15:39:57 +13:00
|
|
|
|
|
|
|
|
// make sure we have received enough bytes for a frame header
|
|
|
|
|
// 3 bytes frame header = (1 byte frame type) + (2 bytes frame length as unsigned 16-bit little endian)
|
|
|
|
|
int frame_header_length = 3;
|
|
|
|
|
if(client.available() >= frame_header_length){
|
|
|
|
|
|
|
|
|
|
// read frame header
|
2026-01-04 17:43:25 +13:00
|
|
|
client.readBytes(&received_frame_header.type, 1);
|
|
|
|
|
client.readBytes((uint8_t*)&received_frame_header.length, 2);
|
2026-01-03 15:39:57 +13:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if we have received a frame header
|
2026-01-03 16:36:19 +13:00
|
|
|
if(hasReceivedFrameHeader()){
|
2026-01-03 15:39:57 +13:00
|
|
|
|
|
|
|
|
// make sure we have received enough bytes for the required frame length
|
|
|
|
|
int available = client.available();
|
2026-01-03 16:36:19 +13:00
|
|
|
int frame_type = received_frame_header.type;
|
|
|
|
|
int frame_length = received_frame_header.length;
|
2026-01-03 15:39:57 +13:00
|
|
|
if(frame_length > available){
|
|
|
|
|
WIFI_DEBUG_PRINTLN("Waiting for %d more bytes", frame_length - available);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// skip frames that are larger than MAX_FRAME_SIZE
|
|
|
|
|
if(frame_length > MAX_FRAME_SIZE){
|
|
|
|
|
WIFI_DEBUG_PRINTLN("Skipping frame: length=%d is larger than MAX_FRAME_SIZE=%d", frame_length, MAX_FRAME_SIZE);
|
|
|
|
|
while(frame_length > 0){
|
|
|
|
|
uint8_t skip[1];
|
|
|
|
|
int skipped = client.read(skip, 1);
|
|
|
|
|
frame_length -= skipped;
|
|
|
|
|
}
|
2026-01-03 16:36:19 +13:00
|
|
|
resetReceivedFrameHeader();
|
2026-01-03 15:39:57 +13:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// skip frames that are not expected type
|
|
|
|
|
// '<' is 0x3c which indicates a frame sent from app to radio
|
|
|
|
|
if(frame_type != '<'){
|
|
|
|
|
WIFI_DEBUG_PRINTLN("Skipping frame: type=0x%x is unexpected", frame_type);
|
|
|
|
|
while(frame_length > 0){
|
|
|
|
|
uint8_t skip[1];
|
|
|
|
|
int skipped = client.read(skip, 1);
|
|
|
|
|
frame_length -= skipped;
|
|
|
|
|
}
|
2026-01-03 16:36:19 +13:00
|
|
|
resetReceivedFrameHeader();
|
2026-01-03 15:39:57 +13:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-04 17:43:25 +13:00
|
|
|
// read frame data to provided buffer
|
|
|
|
|
client.readBytes(dest, frame_length);
|
2026-01-03 15:39:57 +13:00
|
|
|
|
|
|
|
|
// ready for next frame
|
2026-01-03 16:36:19 +13:00
|
|
|
resetReceivedFrameHeader();
|
2026-01-03 15:39:57 +13:00
|
|
|
return frame_length;
|
|
|
|
|
|
2025-03-03 13:26:37 +01:00
|
|
|
}
|
2026-01-03 15:39:57 +13:00
|
|
|
|
2025-03-03 13:26:37 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SerialWifiInterface::isConnected() const {
|
|
|
|
|
return deviceConnected; //pServer != NULL && pServer->getConnectedCount() > 0;
|
|
|
|
|
}
|