从几天以来我一直在寻找这个问题:
我想使用Watson IoT Platform和ESP32(或类似产品)做一个连接的设备(IoT)。该设备带有一些继电器。
在Watson仪表板上,我创建了设备类型,物理/逻辑接口,并将ESP与平台相连。
我在仪表板上创建了一个自定义动作,该自定义动作具有用于标识要切换的继电器的参数(switch2)以及一个不带参数的简单自定义动作(switch)。
问题是,如果生成不带参数(开关)的动作,则会看到回调打印,如果生成带参数(开关2)的动作,则什么也不会发生。我还尝试使用内置的Watson操作“固件更新/下载”,如果我使用固件下载(想要某些参数,例如uri,版本等),则没有任何反应,如果我使用固件更新(不使用)需要参数),我看到订阅的回调。
在这里您可以看到类似ESP的代码arduino
// --------------- HEADERS -------------------
#include <Arduino_JSON.h>
#include <EEPROM.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <PubSubClient.h> //https://github.com/knolleary/pubsubclient/releases/tag/v2.3
WebServer server(80);
char wifi_ssid[100] = "xxxxxx";
char wifi_psw[200] = "xxxxxxx";
// ----- Watson IBM parameters
#define ORG "xxxx"
#define DEVICE_TYPE "Relay"
#define DEVICE_ID "xxxx"
#define TOKEN "xxxxxxxxxxxxxxxx"
char ibmServer[] = ORG ".messaging.internetofthings.ibmcloud.com";
char authMethod[] = "use-token-auth";
char token[] = TOKEN;
char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID;
const char switchTopic[] = "iotdm-1/mgmt/custom/switch-actions-v1/switch2";
const char testTopic[] = "iotdm-1/mgmt/custom/switch-actions-v1/switch"; //"iot-2/cmd/+/fmt/+";
const char observeTopic[] = "iotdm-1/observe";
const char publishTopic[] = "iot-2/evt/status/fmt/json";
const char responseTopic[] = "iotdm-1/response";
const char deviceResponseTopic[] = "iotdevice-1/response";
const char manageTopic[] = "iotdevice-1/mgmt/manage";
const char updateTopic[] = "iotdm-1/mgmt/initiate/firmware/update";
void callback(char* topic, byte* payload, unsigned int payloadLength);
WiFiClient wifiClient;
PubSubClient client(ibmServer, 1883, callback, wifiClient);
bool outputEnable = false;
bool oldOutputEnable = false;
void setup() {
// put your setup code here, to run once:
//Init la porta seriale ed aspetta che si avii
Serial.begin(115200);
while(!Serial) {
delay(1);
}
setupWiFi();
}
void loop() {
// put your main code here, to run repeatedly:
if (!client.loop()) {
mqttConnect();
initManagedDevice();
}
delay(100);
}
// WiFi Settings
void setupWiFi() {
bool state = false;
Serial.println("---- Setup WiFi ----");
Serial.println(wifi_ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(wifi_ssid, wifi_psw);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
mqttConnect();
initManagedDevice();
publishStatus();
Serial.println("");
Serial.print("Connected to ");
Serial.println(wifi_ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
// IBM IoT
void mqttConnect() {
if (!!!client.connected()) {
Serial.print("Reconnecting MQTT client to "); Serial.println(ibmServer);
while (!!!client.connect(clientId, authMethod, token)) {
Serial.print(".");
delay(500);
}
Serial.println();
}
}
void initManagedDevice() {
if (client.subscribe("iotdm-1/response")) {
Serial.println("subscribe to responses OK");
} else {
Serial.println("subscribe to responses FAILED");
}
if (client.subscribe("iotdm-1/device/update")) {
Serial.println("subscribe to update OK");
} else {
Serial.println("subscribe to update FAILED");
}
if (client.subscribe(observeTopic)) {
Serial.println("subscribe to observe OK");
} else {
Serial.println("subscribe to observe FAILED");
}
if (client.subscribe(switchTopic)) {
Serial.println("subscribe to switch OK");
} else {
Serial.println("subscribe to switch FAILED");
}
if (client.subscribe(testTopic)) {
Serial.println("subscribe to Test OK");
} else {
Serial.println("subscribe to Test FAILED");
}
JSONVar root;
JSONVar d;
JSONVar supports;
supports["deviceActions"] = true;
supports["firmwareActions"] = true;
supports["switch-actions-v1"] = true;
d["supports"] = supports;
root["d"] = d;
char buff[300] = "";
JSON.stringify(root).toCharArray(buff, 300);
Serial.println("publishing device metadata:"); Serial.println(buff);
if (client.publish(manageTopic, buff)) {
Serial.println("device Publish ok");
} else {
Serial.print("device Publish failed:");
}
}
void callback(char* topic, byte* payload, unsigned int payloadLength) {
Serial.print("callback invoked for topic: "); Serial.println(topic);
if (strcmp (responseTopic, topic) == 0) {
return; // just print of response for now
}
if (strcmp (updateTopic, topic) == 0) {
handleUpdate(payload);
}
if (strcmp(switchTopic, topic) == 0) {
handleRemoteSwitch(payload);
}
if(strcmp(observeTopic, topic) == 0) {
handleObserve(payload);
}
}
void sendSuccessResponse(const char* reqId) {
JSONVar payload;
payload["rc"] = 200;
payload["reqId"] = reqId;
char buff[300] = "";
JSON.stringify(payload).toCharArray(buff, 300);
if (client.publish(deviceResponseTopic, buff)) {
Serial.println("Success sended");
} else {
Serial.print("Success failed:");
}
}
void publishStatus() {
String payload = "{\"relayStatus\":";
payload += outputEnable;
payload += "}";
Serial.print("Sending payload: "); Serial.println(payload);
if (client.publish(publishTopic, (char*) payload.c_str())) {
Serial.println("Publish OK");
} else {
Serial.println("Publish FAILED");
}
}
void handleUpdate(byte* payload) {
Serial.println("handle Update");
}
void handleObserve(byte* payload) {
JSONVar request = JSON.parse((char*)payload);
JSONVar d = request["d"];
JSONVar fields = d["fields"];
const char* field = fields[0]["field"];
if(strcmp(field, "mgmt.firmware") == 0) {
Serial.println("Upadete the firmware");
sendSuccessResponse(request["reqId"]);
} else {
Serial.println("Unmanaged observe");
Serial.println(request);
}
}
void handleRemoteSwitch(byte* payload) {
Serial.println("handle remote switching");
//invertedSwitch = !invertedSwitch;
outputEnable = !outputEnable;
JSONVar request = JSON.parse((char*)payload);
const char* id = request["reqId"];
sendSuccessResponse(id);
}
感谢所有想帮助我的人。
几天后,我解决了这个问题,我在这里发布了针对同样问题的人的回复:
问题是PubSubClient库,该库仅接受128字节的响应消息(包括标头)。 Watson IBM产生的响应消息比128字节长。
要更改响应消息的缓冲区大小,您需要在行上修改PubSubClient.h文件
#define MQTT_MAX_PACKET_SIZE 128
并使用更大的数字(例如1024)更改128字节。