【问题标题】:Problem with RPC calls from Thingsboard to Arduino (ESP32)从 Thingsboard 到 Arduino (ESP32) 的 RPC 调用问题
【发布时间】:2019-02-26 20:04:56
【问题描述】:

我创建了一个简单的 Arduino 程序,它从我的 thingsboard 仪表板上的 KnobControl 小部件接收位置值并更新伺服位置。该程序基于 ThingsBoard 网站上的 ESP32 Pico Kit GPIO control and DHT22 sensor monitor 示例,并且大部分都在工作。

到目前为止,我的代码能够连接到仪表板并从服务器接收“setPos”和“getPos”RPC 命令,并且到目前为止,它成功地为“setPos”调用运行了相关的 RPC_Response 函数,并且可以移动舵机。

但是,当我刷新仪表板并向控制器发送“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);
    }
  }
}

此外,这是我在刷新仪表板时在串行监视器中看到的响应:

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

当我更新仪表板上旋钮控件的位置时,我在串行监视器中收到以下内容:

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

注意:setPos 调用没有任何问题,这会正确调用 RPC 函数。

最后要注意的是,当我刷新仪表板时,旋钮控件小部件顶部会显示一条错误消息“无法解析响应:[object Object]”。

所以主要问题是没有调用正确的 RPC 函数。您认为问题出在哪里?

【问题讨论】:

    标签: c++ arduino rpc dashboard thingsboard


    【解决方案1】:

    好的,我在 ThingsBoard 包装器库中四处寻找,试图更好地了解处理来自服务器的传入 RPC 文本字符串的代码发生了什么。查看 sendDataArray 函数,我在 for 循环中发现了一段奇怪的代码,它扫描回调数组并将其与传入的 RPC 字符串匹配:

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

    如果调用不包含 params 字段的 RPC 方法,则方法调用将被完全忽略。不幸的是,getPos RPC 调用就是这种情况。所以为了解决这个问题,我只是把上面的代码注释掉了,现在一切正常了。

    @thingsboard 团队,这段代码的最初理由是什么? getValue RPC 调用应该如何传递给客户端进行处理?

    【讨论】:

      【解决方案2】:

      我试图在另一篇文章中解决这个问题,但没有意识到你已经发布了这个。回应没有帮助。我的查询链接如下。

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

      我还注意到,当旋钮控件没有发出任何参数键时,thingsboard.h 包装器基本上会短路草图。由于旋钮控件在执行 getPos 方法时不会发出任何“参数”键,因此您的草图代码永远不会有机会以最新值响应。

      我使用了新的调试终端小部件,并且能够通过发出带有 params 值的 getPos 方法来测试旋钮控件小部件的 RPC 调用。如果您在新调试终端提示符下仅输入“getPos”,您会在调试终端中获得空括号作为响应,并在串行输出中获得 {"method":"getPos"}。就像草图一样。

      如果您在提示符下输入“getPos 1”,您应该在终端窗口中获​​得 SetPosition 值作为响应,并在串行输出中获得“{"method":"getValue","params":1}'。值 1 无关紧要,只是有某种参数可以触发包装器。

      请注意,如果您在调试窗口中输入“setPost 12”,您会将 SetPosition 变量值更新为 12。

      我的结论是旋钮控制小部件已瘫痪。如果要与包装器一起使用,它需要发出一个“参数”密钥对。

      另一个问题,当您让 getPos 在调试终端中工作时,旋钮控件中显示的数值不会更新。不确定这是否是最好的测试。使用仪表板刷新浏览器窗口会产生类似的结果。我认为 getMethod 应该这样做。

      Thingsboard 团队:这里发生了什么,可以改进吗?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-24
        • 1970-01-01
        • 1970-01-01
        • 2021-06-04
        • 1970-01-01
        相关资源
        最近更新 更多