|
44 | 44 | #endif |
45 | 45 |
|
46 | 46 |
|
47 | | -const unsigned long READ_TIMEOUT_MS = 2000; // Timeout when reading a frame |
| 47 | +const unsigned long READ_TIMEOUT_MS = 2000; |
48 | 48 |
|
49 | 49 | class ClientWrapper { |
50 | 50 | public: |
@@ -270,6 +270,7 @@ class EthernetAdapter : public ArduinoNetworkIf { |
270 | 270 | #endif // XCP_ON_ETHERNET_ARDUINO_DRIVER == XCP_ON_ETHERNET_DRIVER_ETHERNET |
271 | 271 |
|
272 | 272 | #if XCP_ON_ETHERNET_ARDUINO_DRIVER == XCP_ON_ETHERNET_DRIVER_WIFI |
| 273 | + |
273 | 274 | class WiFiUdpClientWrapper : public ClientWrapper { |
274 | 275 | public: |
275 | 276 |
|
@@ -359,6 +360,10 @@ class WiFiAdapter : public ArduinoNetworkIf { |
359 | 360 | WiFi.persistent(false); // avoid writing credentials repeatedly to NVS |
360 | 361 | WiFi.mode(WIFI_STA); |
361 | 362 | 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 |
362 | 367 |
|
363 | 368 | // Optional static IP configuration (do this BEFORE begin()) |
364 | 369 | { |
@@ -546,6 +551,120 @@ class FrameParser { |
546 | 551 | } |
547 | 552 | }; |
548 | 553 |
|
| 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 | + |
549 | 668 | static bool ar_read_n(uint8_t* out, size_t n, unsigned long timeout_ms) { |
550 | 669 | if (!s_client) |
551 | 670 | return false; |
@@ -602,7 +721,11 @@ extern "C" { |
602 | 721 | s_timeout_triggered = false; |
603 | 722 | /* Initialize backend network adapter and start listening. */ |
604 | 723 | #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 |
606 | 729 | #else |
607 | 730 | #if defined(XCP_ON_ETHERNET_IP_OCTETS) |
608 | 731 | s_net = new EthernetAdapter(IPAddress(XCP_ON_ETHERNET_IP_OCTETS), XCP_ON_ETHERNET_PORT); |
|
0 commit comments