thingsboard / thingsboard-client-sdk

Client SDK to connect with ThingsBoard IoT Platform from IoT devices (Arduino, Espressif, etc.)
MIT License
163 stars 124 forks source link

Arduino UNO R4 WiFi support #232

Open 31670253 opened 1 month ago

31670253 commented 1 month ago

Hi all I was wondering whether the Arduino UNO R4 WiFi will be supported in future updates?

31670253 commented 1 month ago

I was refered to the SDK repository by a member of the thingsboard forum kindly see the link for previous discussions : Discussion)

MathewHDYT commented 1 month ago

What exactly is the issue with WiFiS3?

Are you sure you can't simply use one of the premade examples for ESP32 on Arduino and then switch the WiFi include to WiFiS3 and change the WiFi initalization.

31670253 commented 1 month ago

Hi Matthew, I face similar issues such as the following forum post: Post

MathewHDYT commented 1 month ago

Are you facing similair issues or the exact same?

If it is this exact issue then please install this library. If this doesn't help then please post the exact issue messages you encountered, without them it is not possible to help further.

31670253 commented 1 month ago

I added the library and also made changes to the WifiS3.h but I still run into errors, Please see my code and errors below installed Librarties are Thingsboard 0.14.0 and TBsub 2.10.0:

include

include

include

constexpr char CURRENT_FIRMWARE_TITLE[] = "TEST"; constexpr char CURRENT_FIRMWARE_VERSION[] = "1.0.1"; constexpr uint8_t FIRMWARE_FAILURE_RETRIES = 12U; constexpr uint16_t FIRMWARE_PACKET_SIZE = 512U; // Reduced size constexpr char WIFI_SSID[] = "xxxxx"; constexpr char WIFI_PASSWORD[] = "password"; constexpr char TOKEN[] = "nr51mxxxxxtvamz7dq7j07"; constexpr char THINGSBOARD_SERVER[] = "xx.xx.xx.xx"; constexpr uint16_t THINGSBOARD_PORT = 1883U; constexpr uint16_t MAX_MESSAGE_SIZE = 522U; constexpr uint32_t SERIAL_DEBUG_BAUD = 115200U;

WiFiClient wifiClient; MqttClient mqttClient(wifiClient);

ThingsBoard tb(mqttClient, MAX_MESSAGE_SIZE);

void InitWiFi() { Serial.println("Connecting to AP ..."); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("Connected to AP"); }

bool reconnect() { if (WiFi.status() == WL_CONNECTED) { return true; } InitWiFi(); return true; }

void setup() { Serial.begin(SERIAL_DEBUG_BAUD); delay(1000); InitWiFi();

}

void loop() { delay(1000);

if (!reconnect()) { return; }

if (!tb.connected()) { if (!tb.connect(THINGSBOARD_SERVER, TOKEN, THINGSBOARD_PORT)) { Serial.println("Failed to connect"); return; } }

tb.loop(); }`

Error: `/Users/nieljoubert/Desktop/Work/new/bare_bone_OTA_TB/bare_bone_OTA_TB.ino:20:44: error: no matching function for call to 'ThingsBoardSized<>::ThingsBoardSized(MqttClient&, const uint16_t&)' ThingsBoard tb(mqttClient, MAX_MESSAGE_SIZE); ^ In file included from /Users/nieljoubert/Desktop/Work/new/bare_bone_OTA_TB/bare_bone_OTA_TB.ino:1:0: /Users/nieljoubert/Documents/Arduino/libraries/ThingsBoard/src/ThingsBoard.h:113:5: note: candidate: template<class ... Args> ThingsBoardSized<MaxResponse, MaxEndpointsAmount, Logger>::ThingsBoardSized(IMQTT_Client&, uint16_t, const size_t&, const Args& ...) ThingsBoardSized(IMQTT_Client & client, uint16_t buffer_size = Default_Payload_Size, size_t const & max_stack_size = Default_Max_Stack_Size, Args const &... args) ^~~~ /Users/nieljoubert/Documents/Arduino/libraries/ThingsBoard/src/ThingsBoard.h:113:5: note: template argument deduction/substitution failed: /Users/nieljoubert/Desktop/Work/new/bare_bone_OTA_TB/bare_bone_OTA_TB.ino:20:44: note: cannot convert 'mqttClient' (type 'MqttClient') to type 'IMQTT_Client&' ThingsBoard tb(mqttClient, MAX_MESSAGE_SIZE); ^ In file included from /Users/nieljoubert/Desktop/Work/new/bare_bone_OTA_TB/bare_bone_OTA_TB.ino:1:0: /Users/nieljoubert/Documents/Arduino/libraries/ThingsBoard/src/ThingsBoard.h:64:7: note: candidate: constexpr ThingsBoardSized<>::ThingsBoardSized(const ThingsBoardSized<>&) class ThingsBoardSized { ^~~~ /Users/nieljoubert/Documents/Arduino/libraries/ThingsBoard/src/ThingsBoard.h:64:7: note: candidate expects 1 argument, 2 provided /Users/nieljoubert/Documents/Arduino/libraries/ThingsBoard/src/ThingsBoard.h:64:7: note: candidate: constexpr ThingsBoardSized<>::ThingsBoardSized(ThingsBoardSized<>&&) /Users/nieljoubert/Documents/Arduino/libraries/ThingsBoard/src/ThingsBoard.h:64:7: note: candidate expects 1 argument, 2 provided Multiple libraries were found for "PubSubClient.h" Used: /Users/nieljoubert/Documents/Arduino/libraries/PubSubClient Not used: /Users/nieljoubert/Documents/Arduino/libraries/TBPubSubClient exit status 1

Compilation error: no matching function for call to 'ThingsBoardSized<>::ThingsBoardSized(MqttClient&, const uint16_t&)'`

MathewHDYT commented 1 month ago

Yu are including ArduinoMqttClient but then create an instace of the MqttClient class.

You have to include the mqtt clients from the library itself the correct include would be Arduino_MQTT_Client and then create an instance Arduino_MQTT_Client mqttClient(wifiClient);

31670253 commented 1 month ago

Thanks for the feedback, I changed it and made sure only TBPubsub is installed otherwise it classes with other Pubsub libraries and ends in a failed state. I am now successfully seeing my device online on TB dashboard. Libraries used was the Thingsboard 0.14.0 and TBPubsubClient 2.10.0 (latest). Just for other people struggling with the same I am going to add the code used, it is a bare minimum code unencrypted :

#include <ThingsBoard.h>
#include <WiFiS3.h>
#include <Arduino_MQTT_Client.h>

constexpr uint16_t FIRMWARE_PACKET_SIZE = 512U; // Reduced size
constexpr char WIFI_SSID[] = "xxxxx";
constexpr char WIFI_PASSWORD[] = "xxxxxx";
constexpr char TOKEN[] = "er16viffdxxxxxnyp7zt";
constexpr char THINGSBOARD_SERVER[] = "xx.xx.xxx.xxx";
constexpr uint16_t THINGSBOARD_PORT = 1883U;
constexpr uint16_t MAX_MESSAGE_SIZE = 522U;
constexpr uint32_t SERIAL_DEBUG_BAUD = 115200U;

WiFiClient wifiClient;
Arduino_MQTT_Client mqttClient(wifiClient);

ThingsBoard tb(mqttClient, MAX_MESSAGE_SIZE);

void InitWiFi() {
Serial.println("Connecting to AP ...");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to AP");
}

bool reconnect() {
if (WiFi.status() == WL_CONNECTED) {
return true;
}
InitWiFi();
return true;
}

void setup() {
Serial.begin(SERIAL_DEBUG_BAUD);
delay(1000);
InitWiFi();

}

void loop() {
delay(1000);

if (!reconnect()) {
return;
}

if (!tb.connected()) {
if (!tb.connect(THINGSBOARD_SERVER, TOKEN, THINGSBOARD_PORT)) {
Serial.println("Failed to connect");
return;
}
}

tb.loop();
}
31670253 commented 1 month ago

Please don't close it as yet since I still want to see if I can proper modify one of your full examples to work with Arduino UNO Wifi R4 , I can then post the code here and you can maybe add it to the examples folder of Thingsboard Library for future Arduino UNO R4 Wifi users. or you can add it? Please let me know

Kind regards

MathewHDYT commented 1 month ago

Just for other people struggling with the same I am going to add the code used, it is a bare minimum code unencrypted :

From what I can see this is exactly the same as all examples in the library made for ESP32 or ESP8266 on Arduino, besides that the WiFi include is now WiFiS3.

I don't think there is a real advantage of copying the examples in the folder completly simply because of one include. Especially because the Arduino UNO Wifi R4 uses the ESP32 under the hood anyway. So using the ESP32 examples would make sense to most people.

31670253 commented 4 weeks ago

Hi, yes, although there is some changes like :

WiFiClient wifiClient; Arduino_MQTT_Client mqttClient(wifiClient); ThingsBoard tb(mqttClient);

The main thing is to be able to receive OTA to arduino UNO, that is what I am struggling with currently, any suggestions?

Here is the example from Arduino library, how would one intergate this to work with TB: OTA

This sketch demonstrates how to make an OTA Update on the UNO R4 WiFi.


#include "WiFiS3.h"
#include "OTAUpdate.h"
#include "root_ca.h"
#include "arduino_secrets.h"

char ssid[] = SECRET_SSID;    // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)

int status = WL_IDLE_STATUS;

OTAUpdate ota;
static char const OTA_FILE_LOCATION[] = "https://downloads.arduino.cc/ota/UNOR4WIFI_Animation.ota";

/* -------------------------------------------------------------------------- */
void setup() {
/* -------------------------------------------------------------------------- */
  //Initialize serial and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

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

  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  // attempt to connect to Wi-Fi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 1 seconds for connection:
    delay(1000);
  }

  printWiFiStatus();

  int ret = ota.begin("/update.bin");
  if(ret != OTAUpdate::OTA_ERROR_NONE) {
    Serial.println("ota.begin() error: ");
    Serial.println((int)ret);
    return;
  }
  ret = ota.setCACert(root_ca);
  if(ret != OTAUpdate::OTA_ERROR_NONE) {
    Serial.println("ota.setCACert() error: ");
    Serial.println((int)ret);
    return;
  }
  int ota_size = ota.download(OTA_FILE_LOCATION, "/update.bin");
  if(ota_size <= 0) {
    Serial.println("ota.download() error: ");
    Serial.println(ota_size);
    return;
  }
  ret = ota.verify();
  if(ret != OTAUpdate::OTA_ERROR_NONE) {
    Serial.println("ota.verify() error: ");
    Serial.println((int)ret);
    return;
  }

  ret = ota.update("/update.bin");
  if(ret != OTAUpdate::OTA_ERROR_NONE) {
    Serial.println("ota.update() error: ");
    Serial.println((int)ret);
    return;
  }
}

/* -------------------------------------------------------------------------- */
void loop() {
/* -------------------------------------------------------------------------- */
  delay(1000);
}

/* -------------------------------------------------------------------------- */
void printWiFiStatus() {
/* -------------------------------------------------------------------------- */
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}
MathewHDYT commented 4 weeks ago

From the code you showed me I don't know the exact methods the from Arduino implemented OTAUpdate provides and I don't know what these methods do.

But you would need to write your own IUpdater Implementation, which has the required interface calls and maps them to the OTAUpdate, which it would probably hold as a member variable. (Adapter Pattern)

Once that is done simply create an instance of it and pass that to the OTA_Callback.


To help you further I would need the link to the GitHub, where the OTAUpdate you are using is implemented, so I can look at the implementation myself and use it to adjust your calls.

The part we require to be implemented is one that receive a binary payload and then writes that somewhere, where it will then be used as firmware after we have finished writing it completely.

For now if the binary on your device is simply contained on an SD card you can use the SD_Card_Updater already contained in the class instead.

gsanta commented 3 weeks ago

I also had to add #define THINGSBOARD_ENABLE_OTA 0 to Configuration.h as the Post suggested to make it work.

31670253 commented 3 weeks ago

To help you further I would need the link to the GitHub, where the OTAUpdate you are using is implemented, so I can look at the implementation myself and use it to adjust your calls.

There was no special library installed this was part of the examples of the Arduino UNO R4 Wifi (only installed board on board manager)

Thanks for opening feature request .

MathewHDYT commented 3 weeks ago

To help you further I would need the link to the GitHub, where the OTAUpdate you are using is implemented, so I can look at the implementation myself and use it to adjust your calls.

There was no special library installed this was part of the examples of the Arduino UNO R4 Wifi (only installed board on board manager)

What I meant is the Source Code to the OTAUpdate file, but I found it myself.

But as the board simply uses an ESP32 as the actual chip, I assume you could simply use any of the 2 ESP32 Updater Implementations. So either Arduino or Espressif Updater. And I'm realtively sure they should simply work.

And how to use those implementation can be seen in the OTA Update examples for ESP32 in the examples folder of this library.

31670253 commented 3 weeks ago

But as the board simply uses an ESP32 as the actual chip, I assume you could simply use any of the 2 ESP32 Updater Implementations. So either Arduino or Espressif Updater. And I'm realtively sure they should simply work.

And how to use those implementation can be seen in the OTA Update examples for ESP32 in the examples folder of this library.

The Arduino UNO R4 WiFi has an ESP32 chip onboard that is correct, but it also has a RA4M1 microprocessor from Renesas which actually handles all your code and then just speaks to the ESP32 via the WifiS3 library. Quoted from website "The Arduino UNO R4 WiFi merges the RA4M1 microprocessor from Renesas with the ESP32-S3 from Espressif"

Therefore one cannot use simply the OTA code from TB written purely for the ESP32 ... there is however examples that shows how to do OTA on these boards. It is just a question on how to merge TB and that example to have a TB OTA for Arduino UNO.

MathewHDYT commented 3 weeks ago

Yeah not 100% sure either but the code can be seen in the link I've commented above and it seems it is using the modem. In the end it is pretty simply, if you want to get OTA updates working you need to somehow write the binary data of the RA4M1.

Not sure how that works, but once you know how to do that you can implment your own IUpdater implementation, the interface and methods are in the README.md documentation. Once that is done simply pass it into the OTA_Update_Callback instance and it should work, as long as the Updater is implemented correctly.

As I do not own an RA4M1, I'm not really able to test or write the Updater myself, and usages like these are exactly the reason that the IUpdater is a simple interface. It allows to support any kind of feature or device as long as the interface implementation is adjusted accordingly.