Skip to content

Commit fb89f6b

Browse files
committed
Add TCP for WiFi
1 parent 383a06c commit fb89f6b

File tree

4 files changed

+142
-2
lines changed

4 files changed

+142
-2
lines changed

inc/xcp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@
9696
#define XCP_ON_ETHERNET_DRIVER_ETHERNET (1)
9797
#define XCP_ON_ETHERNET_DRIVER_WIFI (2)
9898

99+
#define XCP_ON_ETHERNET_USE_UDP (0)
100+
#define XCP_ON_ETHERNET_USE_TCP (1)
101+
102+
#if !defined(XCP_ON_ETHERNET_PROTOCOL)
103+
#define XCP_ON_ETHERNET_PROTOCOL XCP_ON_ETHERNET_USE_UDP
104+
#endif /* * XCP_ON_ETHERNET_PROTOCOL */
105+
99106
#if XCP_ENABLE_EXTERN_C_GUARDS == XCP_ON
100107
#if defined(__cplusplus)
101108
extern "C" {

src/tl/eth/arduino_networking.cpp

Lines changed: 125 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
#endif
4545

4646

47-
const unsigned long READ_TIMEOUT_MS = 2000; // Timeout when reading a frame
47+
const unsigned long READ_TIMEOUT_MS = 2000;
4848

4949
class ClientWrapper {
5050
public:
@@ -270,6 +270,7 @@ class EthernetAdapter : public ArduinoNetworkIf {
270270
#endif // XCP_ON_ETHERNET_ARDUINO_DRIVER == XCP_ON_ETHERNET_DRIVER_ETHERNET
271271

272272
#if XCP_ON_ETHERNET_ARDUINO_DRIVER == XCP_ON_ETHERNET_DRIVER_WIFI
273+
273274
class WiFiUdpClientWrapper : public ClientWrapper {
274275
public:
275276

@@ -359,6 +360,10 @@ class WiFiAdapter : public ArduinoNetworkIf {
359360
WiFi.persistent(false); // avoid writing credentials repeatedly to NVS
360361
WiFi.mode(WIFI_STA);
361362
WiFi.setSleep(false); // keep radio awake during provisioning/UDP XCP
363+
// Optional set TX power (requires Arduino-ESP32 supporting WiFi.setTxPower)
364+
#ifdef XCP_ON_WIFI_TX_POWER
365+
WiFi.setTxPower(XCP_ON_WIFI_TX_POWER);
366+
#endif
362367

363368
// Optional static IP configuration (do this BEFORE begin())
364369
{
@@ -546,6 +551,120 @@ class FrameParser {
546551
}
547552
};
548553

554+
/* TCP client wrapper and adapter for WiFi (ESP32) */
555+
class WiFiClientWrapper : public ClientWrapper {
556+
public:
557+
explicit WiFiClientWrapper(WiFiClient c = WiFiClient()) : m_client(c) {}
558+
559+
void set(WiFiClient c) { m_client = c; }
560+
561+
int available() override { return m_client ? m_client.available() : 0; }
562+
563+
int read_bytes(uint8_t* buf, size_t len) override { return m_client.read(buf, len); }
564+
565+
size_t write_bytes(const uint8_t* buf, size_t len) override { return m_client.write(buf, len); }
566+
567+
bool connected() override { return m_client && m_client.connected(); }
568+
569+
void stop() override {
570+
if (m_client) {
571+
m_client.stop();
572+
}
573+
}
574+
575+
bool is_datagram() const override { return false; }
576+
577+
private:
578+
WiFiClient m_client;
579+
};
580+
581+
class WiFiTcpAdapter : public ArduinoNetworkIf {
582+
public:
583+
WiFiTcpAdapter(const char* s, const char* p, uint16_t port) : m_port(port), m_ssid(s), m_pass(p), m_server(port) {}
584+
585+
bool begin() override {
586+
// Station mode tweaks
587+
WiFi.persistent(false);
588+
WiFi.mode(WIFI_STA);
589+
WiFi.setSleep(false);
590+
#ifdef XCP_ON_WIFI_TX_POWER
591+
WiFi.setTxPower(XCP_ON_WIFI_TX_POWER);
592+
#endif
593+
Serial.begin(115200);
594+
while (!Serial) {
595+
;
596+
}
597+
Serial.println("\nBlueparrot XCP (TCP) on WiFi");
598+
599+
// Optional static IP configuration
600+
#if defined(XCP_ON_ETHERNET_IP_OCTETS)
601+
IPAddress ip(XCP_ON_ETHERNET_IP_OCTETS);
602+
if (!WiFi.config(ip)) {
603+
Serial.println("[WiFi] Failed to apply static IP config");
604+
}
605+
#elif defined(XCP_ON_ETHERNET_IP)
606+
{
607+
IPAddress ip;
608+
ip.fromString(XCP_ON_ETHERNET_IP);
609+
if (!WiFi.config(ip)) {
610+
Serial.println("[WiFi] Failed to apply static IP config (string)");
611+
}
612+
}
613+
#endif
614+
WiFi.begin(m_ssid, m_pass);
615+
unsigned long start = millis();
616+
while (WiFi.status() != WL_CONNECTED && (millis() - start) < 15000UL) {
617+
delay(100);
618+
Serial.print('.');
619+
}
620+
Serial.println();
621+
if (WiFi.status() != WL_CONNECTED) {
622+
Serial.println("[WiFi] Connect failed");
623+
return false;
624+
}
625+
Serial.print("IP: ");
626+
Serial.println(WiFi.localIP());
627+
m_server.begin();
628+
m_server.setNoDelay(true);
629+
return true;
630+
}
631+
632+
ClientWrapper* accept_client() override {
633+
// Accept new clients if none or the existing is disconnected
634+
if (!m_client.connected()) {
635+
WiFiClient incoming = m_server.available();
636+
if (incoming) {
637+
// If an old client existed, drop it
638+
if (m_client) {
639+
m_client.stop();
640+
}
641+
m_client = incoming;
642+
m_client.setNoDelay(true);
643+
m_wrapper.set(m_client);
644+
return &m_wrapper; // Return immediately; Rx handler will poll available()
645+
}
646+
return nullptr;
647+
}
648+
649+
// Existing client remains current; ensure wrapper wraps it
650+
m_wrapper.set(m_client);
651+
return &m_wrapper;
652+
}
653+
654+
String getInfo() override {
655+
IPAddress ip = WiFi.localIP();
656+
return String("WiFi-TCP ") + String(ip[0]) + "." + String(ip[1]) + "." + String(ip[2]) + "." + String(ip[3]);
657+
}
658+
659+
private:
660+
uint16_t m_port;
661+
const char* m_ssid;
662+
const char* m_pass;
663+
WiFiServer m_server;
664+
WiFiClient m_client;
665+
WiFiClientWrapper m_wrapper;
666+
};
667+
549668
static bool ar_read_n(uint8_t* out, size_t n, unsigned long timeout_ms) {
550669
if (!s_client)
551670
return false;
@@ -602,7 +721,11 @@ extern "C" {
602721
s_timeout_triggered = false;
603722
/* Initialize backend network adapter and start listening. */
604723
#if XCP_ON_ETHERNET_ARDUINO_DRIVER == XCP_ON_ETHERNET_DRIVER_WIFI
605-
s_net = new WiFiAdapter(XCP_ON_ETHERNET_WIFI_SSID, XCP_ON_ETHERNET_WIFI_PASSWORD, XCP_ON_ETHERNET_PORT);
724+
#if (XCP_ON_ETHERNET_PROTOCOL == XCP_ON_ETHERNET_USE_TCP)
725+
s_net = new WiFiTcpAdapter(XCP_ON_ETHERNET_WIFI_SSID, XCP_ON_ETHERNET_WIFI_PASSWORD, XCP_ON_ETHERNET_PORT);
726+
#else
727+
s_net = new WiFiAdapter(XCP_ON_ETHERNET_WIFI_SSID, XCP_ON_ETHERNET_WIFI_PASSWORD, XCP_ON_ETHERNET_PORT);
728+
#endif
606729
#else
607730
#if defined(XCP_ON_ETHERNET_IP_OCTETS)
608731
s_net = new EthernetAdapter(IPAddress(XCP_ON_ETHERNET_IP_OCTETS), XCP_ON_ETHERNET_PORT);

tools/arduino/hello_xcp/xcp_config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,17 @@
7575
#elif defined(TP_ETHER)
7676
#define XCP_TRANSPORT_LAYER XCP_ON_ETHERNET
7777

78+
#define XCP_ON_ETHERNET_PROTOCOL XCP_ON_ETHERNET_USE_UDP
7879
#define XCP_ON_ETHERNET_IP_OCTETS 192, 168, 137, 100
7980
#define XCP_ON_ETHERNET_PORT (5555)
8081

8182
#define XCP_ON_ETHERNET_ARDUINO_DRIVER (XCP_ON_ETHERNET_DRIVER_ETHERNET)
8283
#define XCP_ON_ETHERNET_WIFI_SSID ("")
8384
#define XCP_ON_ETHERNET_WIFI_PASSWORD ("")
85+
86+
// Adjust WiFi power, see
87+
// https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/src/WiFiGeneric.h
88+
// #define XCP_ON_WIFI_TX_POWER WIFI_POWER_13dBm
8489
#define XCP_ON_ETHERNET_MAC_ADDRESS { 0xBE, 0xEF, 0xCA, 0xAA, 0xFF, 0xFE }
8590

8691
#define XCP_MAX_CTO (32)

tools/xcp_config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,17 @@
7575
#elif defined(TP_ETHER)
7676
#define XCP_TRANSPORT_LAYER XCP_ON_ETHERNET
7777

78+
#define XCP_ON_ETHERNET_PROTOCOL XCP_ON_ETHERNET_USE_UDP
7879
#define XCP_ON_ETHERNET_IP_OCTETS 192, 168, 137, 100
7980
#define XCP_ON_ETHERNET_PORT (5555)
8081

8182
#define XCP_ON_ETHERNET_ARDUINO_DRIVER (XCP_ON_ETHERNET_DRIVER_ETHERNET)
8283
#define XCP_ON_ETHERNET_WIFI_SSID ("")
8384
#define XCP_ON_ETHERNET_WIFI_PASSWORD ("")
85+
86+
// Adjust WiFi power, see
87+
// https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/src/WiFiGeneric.h
88+
// #define XCP_ON_WIFI_TX_POWER WIFI_POWER_13dBm
8489
#define XCP_ON_ETHERNET_MAC_ADDRESS { 0xBE, 0xEF, 0xCA, 0xAA, 0xFF, 0xFE }
8590

8691
#define XCP_MAX_CTO (32)

0 commit comments

Comments
 (0)