Проблема с вызовами RPC от Thingsboard к Arduino (ESP32) - PullRequest
0 голосов
/ 26 февраля 2019

Я создал простую программу Arduino, которая получает значение позиции из виджета KnobControl на панели инструментов панели инструментов и обновляет позицию сервопривода.Программа основана на примере ESP32 Pico Kit GPIO и сенсорного монитора DHT22 на сайте ThingsBoard и работает в основном .

Пока мой код работаетдля подключения к приборной панели и получения от сервера RPC-команд «setPos» и «getPos», и до сих пор он успешно запускает связанную функцию RPC_Response для вызова «setPos» и может перемещать сервопривод.

Но когда я обновляю приборную панель и она отправляет вызов «getPos» на контроллер, чтобы получить текущее значение сервопривода, я получаю сообщение SDK в последовательном выводе, указывающее, что контроллер получил команду, но связанная функция RPC_Responseникогда не звонил.Я не уверен, что мне не хватает, но вот полный пример кода, который я написал до сих пор:

#include <WiFi.h>
#include <ESP32Servo.h>
#include <ThingsBoard.h>

// Constants
#define SERVO_PIN               19      // Servo Output Pin
#define SERVO_UPDATE_INTERVAL   20      // Speed of servo position updates

// Helper macro to calculate array size
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))

// WiFi Login Info
#define ssid                "IoT"
#define password            "password"

// MQTT Broker IP address:
#define THINGSBOARD_SERVER  "10.10.0.30"

// MQTT Client Info
#define ACCESS_TOKEN "ESP32_DEMO_TOKEN"

// Servo Variables
int minUs = 500;
int maxUs = 2400;
int SetPosition = 0; // ServoMotor Position Setpoint
int Position = 0;    // ServoMotor current position

// Control/Timing Variables
long lastServoTime = 0;       // keeps track of timestamp since the last servo update occured

// Objects
Servo ServoMotor;
WiFiClient espClient;
ThingsBoard client(espClient);

// RPC Callbacks
RPC_Callback callbacks[] = {
  { "setPos", setPosition },
  { "getPos", getPosition },
};

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

  // Initialize Servo
  ServoMotor.setPeriodHertz(50);                  // Standard 50hz servo
  ServoMotor.attach(SERVO_PIN, minUs, maxUs);

  // Initialize the WiFi and MQTT connections
  setup_wifi();
}

void loop() {
  // Update/refresh the Wifi/MQTT connection
  updateWirelessConnection();

  // Update Servo Positions
  updateServo();
}

void updateWirelessConnection()
{
  if (!client.connected()) {
    reconnect();
  }

  client.loop();
}

// Processes function for RPC call "getPos"
// RPC_Data is a JSON variant, that can be queried using operator[]
// See https://arduinojson.org/v5/api/jsonvariant/subscript/ for more details
RPC_Response getPosition(const RPC_Data &data)
{
  Serial.println("Received the get Position Method");
  return RPC_Response(NULL, SetPosition);
}

// Processes function for RPC call "setPos"
// RPC_Data is a JSON variant, that can be queried using operator[]
// See https://arduinojson.org/v5/api/jsonvariant/subscript/ for more details
RPC_Response setPosition(const RPC_Data &data)
{
  Serial.print("Received the Set Position method: ");
  SetPosition = data;
  Serial.println(SetPosition);
  return RPC_Response(NULL, SetPosition);
}

void updateServo()
{
  long currentTime = millis();

  if (currentTime - lastServoTime > SERVO_UPDATE_INTERVAL) {
    lastServoTime = currentTime;

    // Approach the Horizontal set point incrementally and update the servo if applicable
    if (Position != SetPosition) {
      Position = SetPosition;
      ServoMotor.write(Position);
    }
  }
}

void setup_wifi() {
  delay(10);

  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected())
  {
    Serial.print("Attempting MQTT connection...");

    // Attempt to connect
    if (client.connect(THINGSBOARD_SERVER, ACCESS_TOKEN)) {
      Serial.println("connected");

      // Perform a subscription. All consequent data processing will happen in
      // callbacks as denoted by callbacks[] array.
      if (!client.RPC_Subscribe(callbacks, COUNT_OF(callbacks))) {
        Serial.println("Failed to subscribe for RPC");
        return;
      }

      Serial.println("Subscribe done");
    } else {
      Serial.println("Failed to connect. Trying again in 5 seconds...");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

Кроме того, вот ответ, который я вижу в Serial Monitor при обновлении панели инструментов:

{"method":"getPos"}
[SDK] received RPC getPos
[SDK] response {}

Когда я обновляю положение ручки управления на приборной панели, вот что я получаю в Serial Monitor:

{"method":"setPos","params":"135"}
[SDK] received RPC setPos
[SDK] calling RPC setPos
Received the Set Position method: 135
[SDK] response 135

ПРИМЕЧАНИЕ. У меня нет проблем сВызов setPos, это вызывает функцию RPC должным образом.

В качестве последнего замечания, когда я обновляю панель мониторинга, в верхней части окна появляется сообщение об ошибке «Невозможно проанализировать ответ: [объект объекта]».виджет управления ручкой.

Таким образом, основная проблема заключается в том, что правильная функция RPC не вызывается.Как вы думаете, проблема здесь?

Ответы [ 2 ]

0 голосов
/ 20 марта 2019

Я попытался решить проблему в другом сообщении, не понимая, что вы уже опубликовали это.Ответ не помог.Ссылка на мой запрос приведена ниже.

https://github.com/thingsboard/ThingsBoard-Arduino-MQTT-SDK/issues/10#issuecomment-474368259

Я также заметил, что обертка thingsboard.h по существу замыкает эскиз, когда из элемента управления регулятора не выдается ключ params.Поскольку элемент управления knob не выдает никакой клавиши «params» при выполнении метода getPos, ваш код эскиза никогда не получает возможности ответить с самым последним значением.

Я играл с новым виджетом терминала отладки и смогпроверить вызовы RPC виджета управления ручкой, выполнив метод getPos со значением params.Если вы введете просто «getPos» в приглашении «Новый терминал отладки», вы получите пустые скобки в качестве ответа в терминале отладки и {«method»: «getPos»} в последовательном выводе.Точно так же, как эскиз.

Если вы введете «getPos 1» в приглашении, вы должны получить значение SetPosition в качестве ответа в окне терминала и «{» method »:« getValue »,« params »:1} 'в последовательном выводе.Значение 1 не имеет значения, просто есть какой-то параметр для запуска оболочки.

Обратите внимание, что если вы введете 'setPost 12' в окне отладки, вы обновите значение переменной SetPosition до 12.

Мой вывод: виджет управления ручкой поврежден.Для работы с оболочкой необходимо выдать пару ключей 'params'.

Другая проблема, числовое значение, отображаемое в элементе управления knob, не обновляется, когда вы заставляете getPos работать в терминале отладки.,Не уверен, что это лучший тест.Обновление окна браузера с помощью панели инструментов дает аналогичный результат.Я думаю, что getMethod должен сделать это.

Команда Thingsboard: что здесь происходит и можно ли ее улучшить?

0 голосов
/ 26 февраля 2019

ОК, я покопался в библиотеке-оболочке ThingsBoard, чтобы попытаться лучше понять, что происходит с кодом, который обрабатывает входящие текстовые строки RPC с сервера.Заглянув внутрь функции sendDataArray, я обнаружил этот любопытный фрагмент кода внутри цикла for, который сканирует массив обратных вызовов и сопоставляет его с поступающей строкой RPC:

// Do not inform client, if parameter field is missing for some reason
if (!data.containsKey("params")) {
    continue;
}

Если вызывается метод RPC, который не содержитполе params, тогда вызов метода полностью игнорируется.К сожалению, так обстоит дело с RPC-вызовом getPos.Поэтому, чтобы решить проблему, я просто закомментировал приведенный выше код, и теперь все это работает.

@ stuffboard team, каково было исходное обоснование этого кода?Каким образом RPC-вызовы getValue должны передаваться клиенту для обработки?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...