khoih-prog / WebSockets_Generic

WebSocket / Socket.IO Server and Client for Arduino based on RFC6455. Now supporting Adafruit nRF52, Portenta_H7, STM32F/L/H/G/WB/MP1, Teensy, SAM DUE, SAMD21, SAMD51, Arduino SAMD21 (Nano 33 IoT), MKR1000 / MKR1010WiFi, RP2040-based boards using WiFi101, WiFiNINA, WiFi, Ethernet, WT32_ETH01, Teensy 4.1 NativeEthernet/QNEthernet or Portenta_H7 WiFi/Ethernet, etc. so that those boards can be voice-controlled by Alexa. Now supporting websocket only mode for Socket.IO. Ethernet_Generic library is used as default for W5x00
GNU General Public License v3.0
88 stars 22 forks source link

Compatibility with WiFiMulti #33

Closed jonathanlundstrom closed 1 year ago

jonathanlundstrom commented 1 year ago

Hello,

We're developing an embedded application based on the Pico 2040W and are running the maxgerhardt platform with the earlephilhower Arduino Core with WiFiMulti for connectivity. The wireless connection works as intended but we're having troubles establishing a WebSocket connection to our FastAPI server. We've included your library but had to ignore many dependencies, because otherwise it would not build – is this a normal procedure?

Nonetheless, we try to connect using the following code:

#include <string>
#include <Arduino.h>
#include <WiFi.h>
#include <SPI.h>
#include <ArduinoJson.h>
#include <pico/stdlib.h>
#include <WebSocketsClient_Generic.h>

extern "C" {
  #include <acc_version.h>
}

char* chip_id;
WiFiMulti wifi;
String ip_address;
WebSocketsClient webSocket;

bool wifi_connecting = false;
bool alreadyConnected = false;
unsigned long previous_millis = 0;
const char* WIFI_SSID = "SSID";
const char* WIFI_PASS = "PASS";
const uint WIFI_TIMEOUT = 10; // Timeout in seconds

const uint LED_PIN = 14;
const uint SWITCH_PIN = 13;

const uint SPI_MISO = 16;
const uint SPI_MOSI = 19;
const uint SPI_SCK = 18;
const uint SPI_CS = 17;

const uint SEN_EN1 = 20;
const uint SPI_SEL0 = 22;
const uint SPI_SEL1 = 26;
const uint SPI_SEL2 = 27;
const uint SEN_INT1 = 21;

#if (defined(ARDUINO_RASPBERRY_PI_PICO_W))
  #if defined(WEBSOCKETS_NETWORK_TYPE)
    #undef WEBSOCKETS_NETWORK_TYPE
  #endif
  #define WEBSOCKETS_NETWORK_TYPE       NETWORK_RP2040W_WIFI
  #define _WEBSOCKETS_LOGLEVEL_         10
#else
  #error This code is intended to run only on the RP2040W boards ! Please check your Tools->Board setting.
#endif

/// @brief Ready the SPI pins for communication.
void setup_spi() {
  SPI.setRX(SPI_MISO);
  SPI.setCS(SPI_CS); // Documentation says this should be set to high??
  SPI.setSCK(SPI_SCK); // Might need to be high...
  SPI.setTX(SPI_MOSI);
  SPI.begin();
}

void setup_gpio() {
  gpio_init(LED_PIN);
  gpio_init(SWITCH_PIN);
  gpio_set_dir(LED_PIN, GPIO_OUT);
  gpio_set_dir(SWITCH_PIN, GPIO_IN);

  // XE121 pins
  gpio_init(SEN_EN1);
  gpio_init(SPI_SEL0);
  gpio_init(SPI_SEL1);
  gpio_init(SPI_SEL2);
  gpio_init(SEN_INT1);

  // XE121 pin types
  gpio_set_dir(SEN_EN1, GPIO_OUT);
  gpio_set_dir(SPI_SEL0, GPIO_OUT);
  gpio_set_dir(SPI_SEL1, GPIO_OUT);
  gpio_set_dir(SPI_SEL2, GPIO_OUT);
  gpio_set_dir(SEN_INT1, GPIO_IN);

  // XE121 pin defaults
  gpio_put(SEN_EN1, 0);
  gpio_put(SPI_SEL0, 1); // Select sensor 2 according to table in paragraph 2.6
  gpio_put(SPI_SEL1, 0);
  gpio_put(SPI_SEL2, 0);
}

/// @brief Connect to the network.
void connect_to_wifi() {
  wifi_connecting = true;
  if (wifi.run((WIFI_TIMEOUT * 1000)) != WL_CONNECTED) {
    Serial.println("Unable to connect to Wi-Fi, rebooting device in 10 seconds...");
    delay(10000);
    rp2040.reboot();
  } else {
    wifi_connecting = false;
    ip_address = WiFi.localIP().toString();
    Serial.println("Successfully connected to network " + WiFi.softAPSSID());
    Serial.println("Device IP address: " + ip_address);
  }
}

void webSocketEvent(const WStype_t& type, uint8_t * payload, const size_t& length) {
  switch (type) {
    case WStype_DISCONNECTED:
      if (alreadyConnected) {
        Serial.println("[WSc] Disconnected!");
        alreadyConnected = false;
      }

      break;

    case WStype_CONNECTED:
      {
        alreadyConnected = true;

        Serial.print("[WSc] Connected to url: ");
        Serial.println((char *) payload);

        // send message to server when Connected
        webSocket.sendTXT("Connected");
      }

      break;

    case WStype_TEXT:
      Serial.print("[WSc] get text: ");
      Serial.println((char *) payload);

      // send message to server
       webSocket.sendTXT("message here");

      break;

    case WStype_BIN:
      Serial.print("[WSc] get binary length: ");
      Serial.println(length);

      // KH, To check
      // hexdump(payload, length);

      // send data to server
      webSocket.sendBIN(payload, length);

      break;

    case WStype_PING:
      // pong will be send automatically
      Serial.println("[WSc] get ping");

      break;

    case WStype_PONG:
      // answer to a ping we send
      Serial.println("[WSc] get pong");

      break;

    default:
      break;
  }
}

void setup() {
  Serial.begin(9600);

  // Fetch chip id:
  chip_id = (char*) rp2040.getChipID();

  // Check for the WiFi module:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  // Set hostname:
  WiFi.setHostname(chip_id);

  // Register networks:
  wifi.addAP(WIFI_SSID, WIFI_PASS);

  connect_to_wifi();

  String path = (String) "/ws/" + (String) chip_id;
  IPAddress host = IPAddress(192, 168, 1, 212);
  Serial.println(path);
  Serial.println(host.toString());
  webSocket.begin(host, 8000, path);
  webSocket.onEvent(webSocketEvent);

  setup_gpio();
  setup_spi();
}

void loop() {
  unsigned long current_millis = millis();

  if (current_millis - previous_millis >= 5000) {
    previous_millis = current_millis;
    String version = acc_version_get();
    Serial.println("Acconeer SDK version: " + version);
  }

  uint led_state = gpio_get(SWITCH_PIN);
  gpio_put(LED_PIN, led_state);

  if (!WiFi.connected() && !wifi_connecting) {
    Serial.println("Lost connection to Wi-Fi. Attempting to reconnect...");
    connect_to_wifi();
  }

  webSocket.loop();

  delay(25);
}

The code runs, but I never reach a state where it prints anything, and when I check webSocket.isConnected() it returns false. My question is – could this have to do with our Wi-Fi library, or simply because it's unable to connect?

The websocket endpoint is currently hosted on a local device at 192.168.1.212:8000/ws({device_id}. I'm able to connect to this endpoint just fine using Postman or other Websocket programs, but not through this library.

Any help is greatly appreciated! ❤️

Thanks, Jonathan

khoih-prog commented 1 year ago

Hi @jonathanlundstrom

Thanks for using the library and your code is almost perfect, except

#if (defined(ARDUINO_RASPBERRY_PI_PICO_W))
  #if defined(WEBSOCKETS_NETWORK_TYPE)
    #undef WEBSOCKETS_NETWORK_TYPE
  #endif
  #define WEBSOCKETS_NETWORK_TYPE       NETWORK_RP2040W_WIFI
  #define _WEBSOCKETS_LOGLEVEL_         10
#else
  #error This code is intended to run only on the RP2040W boards ! Please check your Tools->Board setting.
#endif

must be placed before

#include <WebSocketsClient_Generic.h>

Moving those lines with

#define WEBSOCKETS_NETWORK_TYPE       NETWORK_RP2040W_WIFI

to the top will solve your issue, unless your WS server is not working

There is nothing wrong with WiFiMulti at all

If you still have issue with PIO, try using Arduino IDE to isolate problem.

Good Luck,



Debug Terninal

Starting WebSockets_Generic_WiFiMulti on RASPBERRY_PI_PICO_W
Successfully connected to network HueNet1
Device IP address: 192.168.2.76
/ws/E6614103E7550737
192.168.2.30
[WSc] Connected to url: /
[WSc] get text: Connected
[WSc] get text: message here
[WSc] get ping
[WSc] Disconnected!
[WSc] Connected to url: /
[WSc] get text: Connected
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
[WSc] get text: message here
...
jonathanlundstrom commented 1 year ago

Thank you!!