نحوه اتصال Raspberry Pi Pico W به ThingsConnect

مقدمه

پس از Raspberry Pi Pico بسیار محبوب، Raspberry Pi Pico W نسخه‌ای با قابلیت بی‌سیم از برد مبتنی بر RP2040 است که اتصال وای‌فای 2.4 گیگاهرتزی 802.11n را اضافه می‌کند.
افزودن اتصال بی‌سیم، بازه‌ی گسترده‌ای از پروژه‌ها را برای Pico W فراهم می‌کند، مانند خواندن حسگرها در فواصل دور، کنترل از راه دور، اتوماسیون خانگی، سرورهای وب کوچک، کنترل بی‌سیم پین‌های GPIO و موارد دیگر.
در مرکز Pico W، RP2040 قرار دارد – همان تراشه‌ای که در Raspberry Pi Pico اصلی استفاده می‌شود – که دو هسته ARM Cortex-M0+ با سرعت 133 مگاهرتز، 256 کیلوبایت رم، 30 پین GPIO و مجموعه‌ای گسترده از گزینه‌های رابط‌بندی را دارا می‌باشد. این تراشه با 2 مگابایت حافظه فلش QSPI برای ذخیره کد و داده همراه است.
اتصال وای‌فای توسط استفاده از یک تراشه بی‌سیم Infineon CYW43439 فعال می‌شود.

در این راهنما، خواهیم آموخت که چگونه دستگاه را در Thingsboard ایجاد کنیم، کتابخانه‌ها و ابزارهای مورد نیاز را نصب کنیم.
سپس کد خود را تغییر داده و آن را بر روی دستگاه بارگذاری کرده و نتایج برنامه نویسی خود را بررسی کرده و با استفاده از داشبورد وارد شده، داده‌ها را در ThingsBoard بررسی می‌کنیم. دستگاه ما با استفاده از قابلیت‌های درخواست‌های مشترک و ویژگی‌های به اشتراک گذاشته شده، با ThingsBoard هماهنگ می‌شود.

به طبع، ما دستگاه خود را با استفاده از قابلیت‌های ارائه شده مانند ویژگی‌های به اشتراک گذاشته شده یا درخواست‌های RPC کنترل خواهیم کرد.

پیش‌نیازها

برای ادامه این راهنما، شما به موارد زیر نیاز دارید:

  •  Raspberry Pi Pico W
  • Arduino IDE
  •  حساب کاربری ThingsBoard

ایجاد دستگاه در ThingsBoard

برای سادگی، ما دستگاه را به صورت دستی با استفاده از رابط کاربری ارائه می کنیم.

به نمونه ThingsBoard خود وارد شوید و به “Entities” بروید. سپس روی صفحه «دستگاه‌ها» کلیک کنید.
روی نماد “+” در گوشه سمت راست بالای جدول کلیک کنید و سپس “Add new device” را انتخاب کنید.
نام دستگاه را وارد کنید به عنوان مثال، “دستگاه من”. در حال حاضر هیچ تغییر دیگری لازم نیست. برای افزودن دستگاه روی «افزودن» کلیک کنید.
دستگاه شما اضافه شده است.

///img

نصب کتابخانه‌ها و ابزارهای مورد نیاز:

نصب برد برای محیط توسعه Arduino:

1. رفتن به بخش File (فایل) > Preferences (تنظیمات) و افزودن آدرس زیر را به فیلد Additional Boards Manager URLs (URLهای اضافی مدیر بردها) اضافه کنید.

https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
  • بروید به منوی Tools (ابزارها) > Board (برد) > Board Manager (مدیر بردها) و برد Raspberry Pi Pico/RP2040 توسط Earle F. Philhower را نصب کنید.

//img

بعد از اتمام نصب، برای انتخاب برد از منوی Board (برد) استفاده کنید:
Tools (ابزارها) > Board (برد) > Raspberry Pi Pico/RP2040 > Raspberry Pi Pico W.

برای نصب ThingsBoard Arduino SDK، باید مراحل زیر را انجام دهید:

  •  به بخش “Tools” (ابزارها) بروید و روی “Manage libraries” (مدیریت کتابخانه‌ها) کلیک کنید.
  •  عبارت “ThingsBoard” را در جعبه جستجو قرار داده و دکمه “INSTALL” (نصب) برای کتابخانه پیدا شده را فشار دهید.

//img

همچنین، برای بردهایی که بر اساس چیپ RP2040 هستند، باید کتابخانه “WiFiNINA” را نصب کنیم.

  • عبارت “WiFiNINA” را در جعبه جستجوی کتابخانه قرار داده و کتابخانه “WiFiNINA by Arduino” را نصب کنید.

//img

در این مرحله، تمام کتابخانه‌ها و ابزارهای مورد نیاز را نصب کرده‌ایم.

اتصال دستگاه به ThingsBoard

برای اتصال دستگاه، ابتدا باید اطلاعات احراز هویت دستگاه را دریافت کنید. ThingsBoard از انواع مختلفی از اطلاعات احراز هویت پشتیبانی می‌کند. ما توصیه می‌کنیم از احراز هویت پیش‌فرض با استفاده از توکن دسترسی استفاده کنید که برای این راهنما تولید شده است.

  • روی ردیف دستگاه در جدول کلیک کنید تا جزئیات دستگاه باز شود.
  • روی “Copy access token” (کپی کردن توکن دسترسی) کلیک کنید. توکن در کلیپبورد شما کپی خواهد شد. لطفاً آن را در یک مکان امن ذخیره کنید.

//img

حالا وقت آن است که برد را برنامه‌ریزی کنید تا به ThingsBoard متصل شود.
برای این کار، می‌توانید از کد زیر استفاده کنید. این کد شامل تمام قابلیت‌های مورد نیاز برای این راهنما است.

#include <ThingsBoard.h>
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#else 
#include <WiFiNINA.h>
#endif

// Wifi credentials
constexpr char WIFI_SSID[] = "YOUR_WIFI_SSID";
constexpr char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";

// See https://thingsboard.io/docs/getting-started-guides/helloworld/
// to understand how to obtain an access token
constexpr char TOKEN[] = "YOUR_ACCESS_TOKEN";

// Thingsboard we want to establish a connection too
constexpr char THINGSBOARD_SERVER[] = "demo.thingsboard.io";
// MQTT port used to communicate with the server, 1883 is the default unencrypted MQTT port.
constexpr uint16_t THINGSBOARD_PORT = 1883U;

// Maximum size packets will ever be sent or received by the underlying MQTT client,
// if the size is to small messages might not be sent or received messages will be discarded
constexpr uint32_t MAX_MESSAGE_SIZE = 512U;

// Baud rate for the debugging serial connection.
// If the Serial output is mangled, ensure to change the monitor speed accordingly to this variable
constexpr uint32_t SERIAL_DEBUG_BAUD = 115200U;


// Initialize underlying client, used to establish a connection
WiFiClient wifiClient;
// Initialize ThingsBoard instance with the maximum needed buffer size
ThingsBoard tb(wifiClient, MAX_MESSAGE_SIZE);

// Attribute names for attribute request and attribute updates functionality

constexpr char BLINKING_INTERVAL_ATTR[] = "blinkingInterval";
constexpr char LED_MODE_ATTR[] = "ledMode";
constexpr char LED_STATE_ATTR[] = "ledState";

// Statuses for subscribing to rpc
bool subscribed = false;

// handle led state and mode changes
volatile bool attributesChanged = false;

// LED modes: 0 - continious state, 1 - blinking
volatile int ledMode = 0;

// Current led state
volatile bool ledState = false;
// Settings for interval in blinking mode
constexpr uint16_t BLINKING_INTERVAL_MS_MIN = 10U;
constexpr uint16_t BLINKING_INTERVAL_MS_MAX = 60000U;
volatile uint16_t blinkingInterval = 1000U;

uint32_t previousStateChange;

// For telemetry
constexpr int16_t telemetrySendInterval = 2000U;
uint32_t previousDataSend;

// List of shared attributes for subscribing to their updates
constexpr std::array<const char *, 2U> SHARED_ATTRIBUTES_LIST = {
  LED_STATE_ATTR,
  BLINKING_INTERVAL_ATTR
};

// List of client attributes for requesting them (Using to initialize device states)
constexpr std::array<const char *, 1U> CLIENT_ATTRIBUTES_LIST = {
  LED_MODE_ATTR
};

const char *getMAC() {
  uint8_t macAddress[WL_MAC_ADDR_LENGTH];
  WiFi.macAddress(macAddress);
  char macStr[12];
  sprintf(macStr, "%x", *macAddress);
  return macStr;
}

const char *getBSSID() {
  uint8_t macAddress[WL_MAC_ADDR_LENGTH];
  WiFi.BSSID(macAddress);
  char macStr[12];
  sprintf(macStr, "%x", *macAddress);
  return macStr;
}

/// @brief Initalizes WiFi connection,
// will endlessly delay until a connection has been successfully established
void InitWiFi() {
  Serial.println("Connecting to AP ...");
  // Attempting to establish a connection to the given WiFi network
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    // Delay 500ms until a connection has been succesfully established
    delay(500);
    Serial.print(".");
  }
  Serial.println("Connected to AP");
}

/// @brief Reconnects the WiFi uses InitWiFi if the connection has been removed
/// @return Returns true as soon as a connection has been established again
const bool reconnect() {
  // Check to ensure we aren't connected yet
  const uint8_t status = WiFi.status();
  if (status == WL_CONNECTED) {
    return true;
  }

  // If we aren't establish a new connection to the given WiFi network
  InitWiFi();
  return true;
}


/// @brief Processes function for RPC call "setLedMode"
/// RPC_Data is a JSON variant, that can be queried using operator[]
/// See https://arduinojson.org/v5/api/jsonvariant/subscript/ for more details
/// @param data Data containing the rpc data that was called and its current value
/// @return Response that should be sent to the cloud. Useful for getMethods
RPC_Response processSetLedMode(const RPC_Data &data) {
  Serial.println("Received the set led state RPC method");

  // Process data
  int new_mode = data;

  Serial.print("Mode to change: ");
  Serial.println(new_mode);

  if (new_mode != 0 && new_mode != 1) {
    return RPC_Response("error", "Unknown mode!");
  }

  ledMode = new_mode;

  attributesChanged = true;

  // Returning current mode
  return RPC_Response("newMode", (int)ledMode);
}

// Optional, keep subscribed shared attributes empty instead,
// and the callback will be called for every shared attribute changed on the device,
// instead of only the one that were entered instead
const std::array<RPC_Callback, 1U> callbacks = {
  RPC_Callback{ "setLedMode", processSetLedMode }
};

/// @brief Update callback that will be called as soon as one of the provided shared attributes changes value,
/// if none are provided we subscribe to any shared attribute change instead
/// @param data Data containing the shared attributes that were changed and their current value
void processSharedAttributes(const Shared_Attribute_Data &data) {
  for (auto it = data.begin(); it != data.end(); ++it) {
    if (strcmp(it->key().c_str(), BLINKING_INTERVAL_ATTR) == 0) {
      const uint16_t new_interval = it->value().as<uint16_t>();
      if (new_interval >= BLINKING_INTERVAL_MS_MIN && new_interval <= BLINKING_INTERVAL_MS_MAX) {
        blinkingInterval = new_interval;
        Serial.print("Updated blinking interval to: ");
        Serial.println(new_interval);
      }
    } else if (strcmp(it->key().c_str(), LED_STATE_ATTR) == 0) {
      ledState = it->value().as<bool>();
      
      Serial.print("Updated state to: ");
      Serial.println(ledState);
    } 
  }
  attributesChanged = true;
}

void processClientAttributes(const Shared_Attribute_Data &data) {
  for (auto it = data.begin(); it != data.end(); ++it) {
    if (strcmp(it->key().c_str(), LED_MODE_ATTR) == 0) {
      const uint16_t new_mode = it->value().as<uint16_t>();
      ledMode = new_mode;
    }
  }
}

const Shared_Attribute_Callback attributes_callback(SHARED_ATTRIBUTES_LIST.cbegin(), SHARED_ATTRIBUTES_LIST.cend(), &processSharedAttributes);
const Attribute_Request_Callback attribute_shared_request_callback(SHARED_ATTRIBUTES_LIST.cbegin(), SHARED_ATTRIBUTES_LIST.cend(), &processSharedAttributes);
const Attribute_Request_Callback attribute_client_request_callback(CLIENT_ATTRIBUTES_LIST.cbegin(), CLIENT_ATTRIBUTES_LIST.cend(), &processClientAttributes);

void setup() {
  // Initalize serial connection for debugging
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
  InitWiFi();
}

void loop() {
  delay(10);

  if (!reconnect()) {
    subscribed = false;
    return;
  }

  if (!tb.connected()) {
    subscribed = false;
    // Connect to the ThingsBoard
    Serial.print("Connecting to: ");
    Serial.print(THINGSBOARD_SERVER);
    Serial.print(" with token ");
    Serial.println(TOKEN);
    if (!tb.connect(THINGSBOARD_SERVER, TOKEN, THINGSBOARD_PORT)) {
      Serial.println("Failed to connect");
      return;
    }
    // Sending a MAC address as an attribute
    tb.sendAttributeString("macAddress", getMAC());
  }

  if (!subscribed) {
    Serial.println("Subscribing for RPC...");
    // Perform a subscription. All consequent data processing will happen in
    // processSetLedState() and processSetLedMode() functions,
    // as denoted by callbacks array.
    if (!tb.RPC_Subscribe(callbacks.cbegin(), callbacks.cend())) {
      Serial.println("Failed to subscribe for RPC");
      return;
    }

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

    Serial.println("Subscribe done");
    subscribed = true;

    // Request current states of shared attributes
    if (!tb.Shared_Attributes_Request(attribute_shared_request_callback)) {
      Serial.println("Failed to request for shared attributes");
      return;
    }

    // Request current states of client attributes
    if (!tb.Client_Attributes_Request(attribute_client_request_callback)) {
      Serial.println("Failed to request for client attributes");
      return;
    }
  }

  if (attributesChanged) {
    attributesChanged = false;
    if (ledMode == 0) {
      previousStateChange = millis();
    }
    tb.sendTelemetryInt(LED_MODE_ATTR, ledMode);
    tb.sendTelemetryBool(LED_STATE_ATTR, ledState);
    tb.sendAttributeInt(LED_MODE_ATTR, ledMode);
    tb.sendAttributeBool(LED_STATE_ATTR, ledState);
  }

  if (ledMode == 1 && millis() - previousStateChange > blinkingInterval) {
    previousStateChange = millis();
    ledState = !ledState;
    digitalWrite(LED_BUILTIN, ledState);
    tb.sendTelemetryBool(LED_STATE_ATTR, ledState);
    tb.sendAttributeBool(LED_STATE_ATTR, ledState);
  }

  // Sending telemetry every telemetrySendInterval time
  if (millis() - previousDataSend > telemetrySendInterval) {
    previousDataSend = millis();
    tb.sendTelemetryInt("temperature", random(10, 20));
    tb.sendAttributeInt("rssi", WiFi.RSSI());
    tb.sendAttributeString("ssid", WIFI_SSID);
    tb.sendAttributeString("bssid", getBSSID());
    tb.sendAttributeString("localIp", String(String(WiFi.localIP()[0]) + "." + String(WiFi.localIP()[1]) + "." + String(WiFi.localIP()[2]) + "." + String(WiFi.localIP()[3])).c_str());
  }

  tb.loop();
}

در کد، جایگزین کردن مکان‌نگه‌دارنده‌ها با شناسه SSID شبکه WiFi، رمز عبور و توکن دسترسی دستگاه ThingsBoard است.

متغیرهای ضروری برای اتصال:

//جدول

...

constexpr char WIFI_SSID[] = "YOUR_WIFI_SSID";
constexpr char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";

constexpr char TOKEN[] = "YOUR_ACCESS_TOKEN";

constexpr char THINGSBOARD_SERVER[] = "demo.thingsboard.io";
constexpr uint16_t THINGSBOARD_PORT = 1883U;

constexpr uint32_t MAX_MESSAGE_SIZE = 512U;
constexpr uint32_t SERIAL_DEBUG_BAUD = 115200U;

...

بخش ارسال داده‌ها در کد (به طور پیش‌فرض، مثال مقدار تصادفی برای کلید دما و برخی اطلاعات WiFi را ارسال می‌کند):

...
    tb.sendTelemetryInt("temperature", random(10, 20));
    tb.sendAttributeInt("rssi", WiFi.RSSI());
    tb.sendAttributeString("ssid", WIFI_SSID);
    tb.sendAttributeString("bssid", getBSSID());
    tb.sendAttributeString("localIp", String(String(WiFi.localIP()[0]) + "." + String(WiFi.localIP()[1]) + "." + String(WiFi.localIP()[2]) + "." + String(WiFi.localIP()[3])).c_str());
...

سپس با فشار دادن دکمه “آپلود” یا ترکیب کلیدهای Ctrl+U، کد را به دستگاه بارگذاری کنید.

//img

بررسی داده ها در ThingsConnect

برای بررسی داده‌ها و دسترسی به امکان ارسال دستورات یا داده به دستگاه، می‌توانید یک داشبورد ایجاد کنید.

ابتدا فایل داشبورد “Check and control device data” را دانلود کنید.

برای اضافه کردن داشبورد به ThingsBoard، باید مراحل زیر را طی کنید:

  •  از طریق منوی اصلی در سمت چپ صفحه به بخش “Dashboards” بروید.
  • بر روی دکمه “+” در گوشه بالا و سمت راست صفحه کلیک کنید و “Import dashboard” را انتخاب کنید.
  •  فایل dashboard.json خود را انتخاب کنید و دکمه “Import” را فشار دهید.
  • حالا می‌توانید داشبورد وارد شده را در جدول مشاهده کنید.

//img

پس از وارد کردن داشبورد، باید برای دستگاه خود نام مستعار موجودیت را انتخاب کنیم.

برای انجام این کار، باید روی آیکون مداد کلیک کنید و “Entity Aliases” را انتخاب کنید، سپس نام مستعار “My device” را انتخاب کرده و با کلیک بر روی آیکون مداد، آن را برای ویرایش باز کنید.

سپس یک دستگاه با نام “My device” را از لیست کشویی انتخاب کنید و مستعار موجودیت را ذخیره کنید. حالا باید بتوانید داده‌ها را از دستگاه مشاهده کنید.

برای بررسی داده‌ها از دستگاه خود، باید داشبورد وارد شده را باز کنید:

  •  با کلیک بر روی آن در جدول، داشبورد را باز کنید.
  •  نمایی از داشبورد برای بررسی داده‌ها و کنترل دستگاه خود.
  •  ویژگی‌های دریافت شده از دستگاه.
  •  اطلاعات دستگاه از سرور ThingsBoard.
  •  ویجتی برای مشاهده تاریخچه تغییرات حالت LED.
  •  ویجتی برای مشاهده تاریخچه دمای شبیه‌سازی شده.

//img

هماهنگ سازی وضعیت دستگاه با استفاده از درخواست‌های مشتری و ویژگی‌های مشترک

به منظور دریافت وضعیت دستگاه از ThingsBoard در زمان راه‌اندازی، ما این قابلیت را در کد داریم.
بخش‌های مسئول کد مثال عبارتند از:

  • تماس‌های بازخورد ویژگی:
...
void processSharedAttributes(const Shared_Attribute_Data &data) {
  for (auto it = data.begin(); it != data.end(); ++it) {
    if (strcmp(it->key().c_str(), BLINKING_INTERVAL_ATTR) == 0) {
      const uint16_t new_interval = it->value().as<uint16_t>();
      if (new_interval >= BLINKING_INTERVAL_MS_MIN && new_interval <= BLINKING_INTERVAL_MS_MAX) {
        blinkingInterval = new_interval;
        Serial.print("Updated blinking interval to: ");
        Serial.println(new_interval);
      }
    } else if(strcmp(it->key().c_str(), LED_STATE_ATTR) == 0) {
      ledState = it->value().as<bool>();
      digitalWrite(LED_BUILTIN, ledState ? HIGH : LOW);
      Serial.print("Updated state to: ");
      Serial.println(ledState);
    }
  }
  attributesChanged = true;
}

void processClientAttributes(const Shared_Attribute_Data &data) {
  for (auto it = data.begin(); it != data.end(); ++it) {
    if (strcmp(it->key().c_str(), LED_MODE_ATTR) == 0) {
      const uint16_t new_mode = it->value().as<uint16_t>();
      ledMode = new_mode;
    }
  }
}
...
const Attribute_Request_Callback attribute_shared_request_callback(SHARED_ATTRIBUTES_LIST.cbegin(), SHARED_ATTRIBUTES_LIST.cend(), &processSharedAttributes);
const Attribute_Request_Callback attribute_client_request_callback(CLIENT_ATTRIBUTES_LIST.cbegin(), CLIENT_ATTRIBUTES_LIST.cend(), &processClientAttributes);
...

همانطور که مشاهده می‌کنید، ما ۲ تماس بازخورد داریم، اولی برای ویژگی‌های مشترک و دومی برای ویژگی‌های مشتری.
تماس بازخورد اولیه پاسخی را با فاصله‌ی چشمک‌زنی دریافت می‌کند تا دوره صحیح چشمک‌زنی را تنظیم کند.
تماس بازخورد دومی حالت و وضعیت LED را دریافت و آن‌ها را ذخیره و تنظیم می‌کند.
این قابلیت به ما اجازه می‌دهد که پس از راه‌اندازی مجدد، وضعیت واقعی را حفظ کنیم.

  • درخواست‌های ویژگی:
...
  // Request current states of shared attributes
  if (!tb.Shared_Attributes_Request(attribute_shared_request_callback)) {
    Serial.println("Failed to request for shared attributes");
    return;
  }

  // Request current states of client attributes
  if (!tb.Client_Attributes_Request(attribute_client_request_callback)) {
    Serial.println("Failed to request for client attributes");
    return;
  }
...

برای اینکه تماس‌های بازخورد ما بتوانند داده‌ها را دریافت کنند، باید یک درخواست به ThingsBoard ارسال کنیم.

کنترل دستگاه با استفاده از ویژگی‌های مشترک

همچنین ما می‌توانیم با استفاده از قابلیت به‌روزرسانی ویژگی‌های مشترک، دوره چشمک‌زنی را تغییر دهیم.

  • برای تغییر دوره چشمک‌زنی، فقط کافیست مقدار را در داشبورد خود تغییر دهیم.
  • بعد از اعمال تغییر با فشار دادن علامت تیک، یک پیام تأیید را خواهید دید.

//img

برای تغییر وضعیت وقتی که چشمک‌زنی غیرفعال است، می‌توانیم از سوئیچ موجود در همان ویجت استفاده کنیم:

  • این کار فقط زمانی انجام می‌شود که حالت چشمک‌زنی غیرفعال است.

//img

برای دستیابی به این مورد، ما یک متغیر به نام “blinkingInterval” داریم که در بخش‌های زیر از کد استفاده می‌شود:

  • تماس بازخورد برای به‌روزرسانی ویژگی‌های مشترک:
...

void processSharedAttributes(const Shared_Attribute_Data &data) {
  for (auto it = data.begin(); it != data.end(); ++it) {
    if (strcmp(it->key().c_str(), BLINKING_INTERVAL_ATTR) == 0) {
      const uint16_t new_interval = it->value().as<uint16_t>();
      if (new_interval >= BLINKING_INTERVAL_MS_MIN && new_interval <= BLINKING_INTERVAL_MS_MAX) {
        blinkingInterval = new_interval;
        Serial.print("Updated blinking interval to: ");
        Serial.println(new_interval);
      }
    } else if(strcmp(it->key().c_str(), LED_STATE_ATTR) == 0) {
      ledState = it->value().as<bool>();
      digitalWrite(LED_BUILTIN, ledState ? HIGH : LOW);
      Serial.print("Updated state to: ");
      Serial.println(ledState);
    }
  }
  attributesChanged = true;
}

...
const Shared_Attribute_Callback attributes_callback(SHARED_ATTRIBUTES_LIST.cbegin(), SHARED_ATTRIBUTES_LIST.cend(), &processSharedAttributes);
...
  • درخواست اشتراک برای به‌روزرسانی ویژگی‌های مشترک:
...
    if (!tb.Shared_Attributes_Request(attribute_shared_request_callback)) {
      Serial.println("Failed to request for shared attributes");
      return;
    }
...
  • بخشی از کد برای چشمک‌زنی:
...

  if (ledMode == 1 && millis() - previousStateChange > blinkingInterval) {
    previousStateChange = millis();
    ledState = !ledState;
    digitalWrite(LED_BUILTIN, ledState);
    tb.sendTelemetryBool(LED_STATE_ATTR, ledState);
    tb.sendAttributeBool(LED_STATE_ATTR, ledState);
    if (LED_BUILTIN == 99) {
      Serial.print("LED state changed to: ");
      Serial.println(ledState);
    }
  }
...

شما می‌توانید منطق را تغییر دهید تا به اهداف خود برسید و پردازشی برای ویژگی‌های خود اضافه کنید.

کنترل دستگاه با استفاده از RPC

شما می‌توانید به طور دستی وضعیت LED را تغییر دهید و حالت را بین روشنایی مداوم و چشمک‌زنی تغییر دهید. برای این کار، می‌توانید از بخش‌های زیر در داشبورد ما استفاده کنید:

  • با استفاده از ابزارک سوئیچ، وضعیت LED را به روشنایی مداوم تغییر دهید.
  • با استفاده از ابزارک سوئیچ گرد، وضعیت LED را به حالت چشمک‌زنی تغییر دهید.

///img

لطفاً توجه کنید که شما تنها می‌توانید وضعیت LED را تغییر دهید اگر حالت چشمک‌زنی غیرفعال باشد.

در مثال کد، ما قابلیت بررسی دستورات RPC را داریم.
برای دسترسی به کنترل دستگاه، از بخش‌های زیر در کد استفاده کرده‌ایم:

  • تماس بازخورد برای درخواست‌های RPC:
...

RPC_Response processSetLedMode(const RPC_Data &data) {
  Serial.println("Received the set led state RPC method");

  // Process data
  int new_mode = data;

  Serial.print("Mode to change: ");
  Serial.println(new_mode);

  if (new_mode != 0 && new_mode != 1) {
    return RPC_Response("error", "Unknown mode!");
  }

  ledMode = new_mode;

  attributesChanged = true;

  // Returning current mode
  return RPC_Response("newMode", (int)ledMode);
}

...

const std::array<RPC_Callback, 1U> callbacks = {
  RPC_Callback{ "setLedMode", processSetLedMode }
};

...
  • درخواست اشتراک برای درخواست‌های RPC:
...
    if (!tb.RPC_Subscribe(callbacks.cbegin(), callbacks.cend())) {
      Serial.println("Failed to subscribe for RPC");
      return;
    }
...

شما می‌توانید کد را تغییر دهید تا به اهداف خود برسید و پردازشی برای دستورات RPC خود اضافه کنید.

نتیجه‌گیری

با دانشی که در این راهنما آورده شده است، شما به راحتی می‌توانید Raspberry Pi Pico W خود را به ThingsBoard متصل کنید و داده‌ها را ارسال کنید.

برای کسب اطلاعات بیشتر درباره مفاهیم و ویژگی‌های کلیدی، به مستندات پلتفرم مراجعه کنید. به عنوان مثال، قوانین هشدار یا داشبوردها را پیکربندی کنید.

عناوین هر بخش