thingsboard-client-sdk: [Question] Problem subscribing to shared attributes

Hey guys,

i want to subscribe my client to shared attributes and RPC methods simultaneously, like here #63. The problem is that i don’t get that far, because of the code not compiling. The error lays in the code section where define the subsricption to shared attribute updates. I followed the example 0006 from the v0.8.0 release. Did i miss something?

Any advice is very appriciated! Thank you in advance.

Greetings Reno

Here is my code:

#include "Pinout.h"       // Pinbelegung des NodeMCUs
#include "ESP8266WiFi.h"  // "File" > "Preferences..." > "Additional board manager URls:" > http://arduino.esp8266.com/stable/package_esp8266com_index.json
#include "ThingsBoard.h"  // Version v0.8.0 by ThingsBoard

// Intenet-Zugangsdaten:
#define WIFI_AP "XXX"
#define WIFI_PASSWORD "XXX"

// ThingsBoard (TB) Zugangsdaten:
#define TB_TOKEN "XXX"  // Access Token des TB-Devices (Aktuator)
#define TB_SERVER "demo.thingsboard.io"  // Alternativ IPv4 des Servers über den die TB gehostet wird (Bsp.: Docker)
#define TB_PORT 1883


constexpr std::array<const char*, 7U> SUBSCRIBED_SHARED_ATTRIBUTES = {
  "fw_checksum",
  "fw_checksum_algorithm",
  "fw_size",
  "fw_tag",
  "fw_title",
  "fw_version",
  "test"
};

// Initialisierung
WiFiClient wifiClient;                      // Erstellung einer ESP8266WiFi-Instanz des Typs
ThingsBoard client(wifiClient);   // Instanz wird zu einem TB-Client (?) Sized<256>

// Weitere Parameter:
int status = WL_IDLE_STATUS;
/* unsigned long lastSend;                     // Updatetimer */

void setup() {

  pinMode(LED_BUILTIN, OUTPUT);  // Auf NodeMCU integrierte LED wird angemacht (Betreibszustandanzeige)
  Serial.begin(9600);                            // Initiierung des seriellen Monitors (SM) zum Debugen (Baudrate)
  InitWiFi();                                    // Aufbau der Internetverbindung
  client.connect(TB_SERVER, TB_TOKEN, TB_PORT);  // Verbindung mit dem MQTT-Broker von TB (Port:)
  /*   lastSend = 0;                                   // Initialisierung des Updatetimers */
}

void loop() {

  // Wiederherstellung der Verbindung zu TB (+ Prüfung der Internetverbindung)
  if (!client.connected()) {
    reconnect();
  }

  subscribeRPC();               // Aufbau und Aufrechterhaltung der RPC-Kommunikation mit TB
  subscribeSharedAttributes();  // Subscribt Änderungen von Shared Attributes

  client.loop();
}

///////////////////// RPC-Kommunikation /////////////////////

RPC_Response processSwitchChange(const RPC_Data& data) {
  Serial.println("Received 'processSwitchChange'-method: ");
  char params[10];
  serializeJson(data, params);
  String _params = params;

  if (_params == "true") {
    Serial.println("SWITCH: ON");
    client.sendAttributeBool("ledStatus", true);
    return RPC_Response("processSwitchChange", "true");

  } else if (_params == "false") {
    Serial.println("SWITCH: OFF");
    client.sendAttributeBool("ledStatus", false);
    return RPC_Response("processSwitchChange", "false");
  }
}

const size_t RPCCallbackSize = 1;
RPC_Callback RPCCallbacks[RPCCallbackSize] = {
  { "processSwitchChange", processSwitchChange }
};

bool rpc_subscribed = false;  //RPC-Subscribe Status


///////////////////// Shared Attributes /////////////////////

void processSharedAttributeUpdate(const Shared_Attribute_Data &data) {
  for (auto it = data.begin(); it != data.end(); ++it) {
    Serial.println(it->key().c_str());
    // Shared attributes have to be parsed by their type.
    Serial.println(it->value().as<const char*>());
  }

  int jsonSize = JSON_STRING_SIZE(measureJson(data));
  char buffer[jsonSize];
  serializeJson(data, buffer, jsonSize);
  Serial.println(buffer);
}

const Shared_Attribute_Callback SharedAttributesCallback(SUBSCRIBED_SHARED_ATTRIBUTES.cbegin(), SUBSCRIBED_SHARED_ATTRIBUTES.cend(), processSharedAttributeUpdate);

/* const size_t SharedCallbackSize = 1;
Shared_Attribute_Callback SharedAttributesCallback[SharedCallbackSize] = {
  processSharedAttributeUpdate
}; */ // TB SDK v0.6

bool att_subscribed = false;

//////////////////// Weitere Funktionen /////////////////////

// Funktion - Aufbau der Internetverbindung
void InitWiFi() {

  Serial.print("Connecting to Access Point...");
  WiFi.begin(WIFI_AP, WIFI_PASSWORD);  // Eingabe der Zugangsdaten

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);  // "." bis Verbindung hergestellt ist
    Serial.print(".");
  }
  Serial.println();
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());
}

// Funktion - Wiederherstellung der Verbindung zu TB
void reconnect() {
  while (!client.connected()) {
    status = WiFi.status();

    if (status != WL_CONNECTED) {  // Prüft zunächst die Internetverbindung
      InitWiFi();
    }

    // Wiederherstellung der Verbindung mit dem festgelegten TB-Device
    Serial.print("Connecting to ThingsBoard Device ...");
    if (client.connect(TB_SERVER, TB_TOKEN, TB_PORT)) {
      Serial.println("[DONE]");
    } else {
      Serial.print("[FAILED] Retrying in 5 seconds]");
      delay(5000);
      //Serial.print(client.state());
      //Serial.println(" : retrying in 5 seconds]");
    }
  }
}

// Funktion - Aufbau und Aufrechterhaltung der RPC-Kommunikation
void subscribeRPC() {
  if (!rpc_subscribed) {
    Serial.println("Subscribing for RPC...");

    if (!client.RPC_Subscribe(RPCCallbacks, RPCCallbackSize)) {
      Serial.println("Failed to subscribe for RPC");
      return;
    }

    Serial.println("RPC-Subscription done");
    rpc_subscribed = true;
  }
}

// Funktion - Subsribt Änderungen 
void subscribeSharedAttributes() {

  if (!att_subscribed) {
    Serial.println("Subscribing for shared attribute updates...");

    if (!client.Shared_Attributes_Subscribe(SharedAttributesCallback)) {
      Serial.println("Failed to subscribe for shared attribute updates");
      return;
    }

    Serial.println("Shared Attributes-Subscription done");
    att_subscribed = true;
  }
}

And this is the error i get:

C:\Users\Renaud Kenfack\Documents\Arduino\Code_Aktuator_TBv080\Code_Aktuator_TBv080.ino:98:162: error: no matching function for call to 'Shared_Attribute_Callback::Shared_Attribute_Callback(std::array<const char*, 7>::const_iterator, std::array<const char*, 7>::const_iterator, void (&)(const Shared_Attribute_Data&))'
   98 | }
      |                                                                                                                                                                  ^
In file included from C:\Users\Renaud Kenfack\Documents\Arduino\Code_Aktuator_TBv080\Code_Aktuator_TBv080.ino:3:
c:\Users\Renaud Kenfack\Documents\Arduino\libraries\ThingsBoard\src/ThingsBoard.h:145:12: note: candidate: 'Shared_Attribute_Callback::Shared_Attribute_Callback(Shared_Attribute_Callback::processFn)'
  145 |     inline Shared_Attribute_Callback(processFn cb)
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~
c:\Users\Renaud Kenfack\Documents\Arduino\libraries\ThingsBoard\src/ThingsBoard.h:145:12: note:   candidate expects 1 argument, 3 provided
c:\Users\Renaud Kenfack\Documents\Arduino\libraries\ThingsBoard\src/ThingsBoard.h:140:12: note: candidate: 'Shared_Attribute_Callback::Shared_Attribute_Callback()'
  140 |     inline Shared_Attribute_Callback()
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~
c:\Users\Renaud Kenfack\Documents\Arduino\libraries\ThingsBoard\src/ThingsBoard.h:140:12: note:   candidate expects 0 arguments, 3 provided
c:\Users\Renaud Kenfack\Documents\Arduino\libraries\ThingsBoard\src/ThingsBoard.h:131:7: note: candidate: 'constexpr Shared_Attribute_Callback::Shared_Attribute_Callback(const Shared_Attribute_Callback&)'
  131 | class Shared_Attribute_Callback {
      |       ^~~~~~~~~~~~~~~~~~~~~~~~~
c:\Users\Renaud Kenfack\Documents\Arduino\libraries\ThingsBoard\src/ThingsBoard.h:131:7: note:   candidate expects 1 argument, 3 provided
c:\Users\Renaud Kenfack\Documents\Arduino\libraries\ThingsBoard\src/ThingsBoard.h:131:7: note: candidate: 'constexpr Shared_Attribute_Callback::Shared_Attribute_Callback(Shared_Attribute_Callback&&)'
c:\Users\Renaud Kenfack\Documents\Arduino\libraries\ThingsBoard\src/ThingsBoard.h:131:7: note:   candidate expects 1 argument, 3 provided
C:\Users\Renaud Kenfack\Documents\Arduino\Code_Aktuator_TBv080\Code_Aktuator_TBv080.ino: In function 'void subscribeSharedAttributes()':
C:\Users\Renaud Kenfack\Documents\Arduino\Code_Aktuator_TBv080\Code_Aktuator_TBv080.ino:167:69: error: no matching function for call to 'ThingsBoardSized<>::Shared_Attributes_Subscribe(const Shared_Attribute_Callback&)'
  167 | 
      |                                                                     ^
In file included from C:\Users\Renaud Kenfack\Documents\Arduino\Code_Aktuator_TBv080\Code_Aktuator_TBv080.ino:3:
c:\Users\Renaud Kenfack\Documents\Arduino\libraries\ThingsBoard\src/ThingsBoard.h:613:10: note: candidate: 'bool ThingsBoardSized<PayloadSize, MaxFieldsAmt, Logger>::Shared_Attributes_Subscribe(const Shared_Attribute_Callback*, size_t) [with unsigned int PayloadSize = 64; unsigned int MaxFieldsAmt = 8; Logger = ThingsBoardDefaultLogger; size_t = unsigned int]'
  613 |     bool Shared_Attributes_Subscribe(const Shared_Attribute_Callback *callbacks, size_t callbacks_size) {
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~
c:\Users\Renaud Kenfack\Documents\Arduino\libraries\ThingsBoard\src/ThingsBoard.h:613:10: note:   candidate expects 2 arguments, 1 provided

exit status 1

Compilation error: no matching function for call to 'Shared_Attribute_Callback::Shared_Attribute_Callback(std::array<const char*, 7>::const_iterator, std::array<const char*, 7>::const_iterator, void (&)(const Shared_Attribute_Data&))'

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 36 (27 by maintainers)

Commits related to this issue

Most upvoted comments

Hi @MathewHDYT,

I have done some experiments today and discovered that only moving all of strings gives ability to work stable. (In other cases after try to process the saved string in physical memory it produces runtime exception). Also I discovered that we have an issue with std::string::replace method - it also produces the error, I’m currently working with it.


Decoding stack results
0x4020f14c: loop_wrapper() at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_main.cpp line 252
0x4020ee66: __unhandled_exception_cpp() at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_main.cpp line 307
0x40216760: _Unwind_RaiseException at /workdir/repo/gcc-gnu/libgcc/unwind.inc line 93
0x402241c4: __cxxabiv1::__terminate(void (*)()) at /workdir/repo/gcc-gnu/libstdc++-v3/libsupc++/eh_terminate.cc line 49
0x4022f358: std::length_error::~length_error() at /workdir/repo/gcc-gnu/libstdc++-v3/src/c++98/stdexcept.cc line 60
0x402324c0: std::length_error::length_error(char const*) at /workdir/repo/gcc-gnu/libstdc++-v3/src/c++11/cow-stdexcept.cc line 115
0x402245ee: std::__throw_length_error(char const*) at /workdir/repo/gcc-gnu/libstdc++-v3/src/c++11/functexcept.cc line 78
0x40225540: std::__cxx11::basic_string  , std::allocator  >::_M_check_length(unsigned int, unsigned int, char const*) const at /workdir/arena.x86_64/gcc-gnu/xtensa-lx106-elf/libstdc++-v3/include/bits/basic_string.h line 903
0x402259f0: std::__cxx11::basic_string  , std::allocator  >::_M_replace(unsigned int, unsigned int, char const*, unsigned int) at /workdir/arena.x86_64/gcc-gnu/xtensa-lx106-elf/libstdc++-v3/include/bits/basic_string.h line 903
0x4020d4e8: HardwareSerial::write(unsigned char const*, unsigned int) at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/HardwareSerial.h line 193
0x4020a8d6: ThingsBoardSized256u, 8u, ThingsBoardDefaultLogger>::process_rpc_message(char*, unsigned char*, unsigned int) at /home/imbeacon/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.1.0-gcc10.3-e5f9fec/xtensa-lx106-elf/include/c++/10.3.0/bits/basic_string.h line 1937
0x4021f7a4: __ssputs_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c line 232
0x40218ae8: _printf_i at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c line 246
0x4020fee4: uart_write(uart_t*, char const*, size_t) at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/uart.cpp line 547
0x40100890: check_poison_neighbors(umm_heap_context_t*, uint16_t) at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_local.c line 59
0x4010075c: get_poisoned(void*, size_t) at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_poison.c line 121
0x40100db4: umm_malloc(size_t) at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_malloc.cpp line 912
0x4021ba95: vsnprintf at /workdir/repo/newlib/newlib/libc/stdio/vsnprintf.c line 40
0x40211fe0: ArduinoJson6200_F1::SafeBoolIdom ::safeBoolHelper() const at /home/imbeacon/Arduino/libraries/ArduinoJson/src/ArduinoJson/Misc/SafeBoolIdiom.hpp line 15
0x4020fee4: uart_write(uart_t*, char const*, size_t) at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/uart.cpp line 547
0x4020ac84: ThingsBoardSized256u, 8u, ThingsBoardDefaultLogger>::onMQTTMessage(char*, unsigned char*, unsigned int) at /home/imbeacon/Arduino/libraries/thingsboard-arduino-sdk/src/ThingsBoard.h line 2300
0x40100be4: get_unpoisoned_check_neighbors(void*, char const*, int) at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_local.c line 111
0x40100932: umm_free_core(umm_heap_context_t*, void*) at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_malloc.cpp line 642
0x40100d72: umm_free(void*) at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/umm_malloc/umm_malloc.cpp line 688
0x40245934: mem_free at core/mem.c line 236
0x40209b36: loop() at /home/imbeacon/Arduino/libraries/thingsboard-arduino-sdk/src/ThingsBoard.h line 481
0x40245dea: pbuf_free_LWIP2 at core/pbuf.c line 786
0x4020c3e5: ClientContext::_consume(unsigned int) at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/libraries/ESP8266WiFi/src/include/ClientContext.h line 580
0x4020c4de: WiFiClient::read() at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/libraries/ESP8266WiFi/src/include/ClientContext.h line 249
0x4020c9b4: PubSubClient::readByte(unsigned char*) at /home/imbeacon/Arduino/libraries/PubSubClient/src/PubSubClient.cpp line 297
0x4020cadf: PubSubClient::readPacket(unsigned char*) at /home/imbeacon/Arduino/libraries/PubSubClient/src/PubSubClient.cpp line 350
0x4020cfa4: PubSubClient::loop() at /home/imbeacon/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.1.0-gcc10.3-e5f9fec/xtensa-lx106-elf/include/c++/10.3.0/bits/std_function.h line 617
0x40209aa7: loop() at /home/imbeacon/Arduino/complex_example/complex_example.ino line 284
0x4020f16c: loop_wrapper() at /home/imbeacon/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/cores/esp8266/core_esp8266_main.cpp line 258

Unfortunately cannot test your variant of the code, because have no electricity right now.

Hi @MathewHDYT ,

I have implemented one complex example sketch for documentation and faced the same issue, it was solved(at least for testing) only after removing PROGMEM from all variables in ThingsBoard.h. But I think it may be caused because of WiFiClient on ESP8266 doesn’t want to work with saved in flash memory variables correctly.

Good to know are you sure it is every variable because for example the log messages to Serial should definitely work.

A simple fix would just be to remove ‘PROGMEM’ if the ESP32 isn’t used.

What do you think @imbeacon.

Unfortunately I cannot say that it is every variable, it was a quick investigation. I also thought to separate strings initialisation depending on board. At least for quick fix.

  1. I would recommend to rename #define WIFI_AP to WIFI_SSID, mainly because WIFI_AP is already defined in the WiFi library and you are overwriting that define

Okay, that’s good to know.

  1. The client you created ThingsBoard client(wifiClient); has the default size of 64 bytes for messages only, I would probably increase that or messages might be discarded use ThingsBoardSized<256> client(wifiClient); to increase the maximal message size to 256 that should be enough for your use case (increase it even more if message seem to not arrive)

It wasn’t issue so far, but I will resort in case of a problem 😃

  1. The syntax for RPC subscription is wrong you are passing a c style array instead of an std::array

The problem is that i don’t get that far, because of the code not compiling.

I didn’t changed that part of the code yet, but this will also be corrected

  1. Are you really sure the version you checked out is 0.8.0

I checked and my Arduino Sketch enviroment was still including the older TB library (0.6.1). Thanks for the hint!

I’ll report back 😃