Search code examples
mqttpublish-subscribeesp8266watson-iot

I can not subscribe with ESP8266-ESP32 in IBM Watson IOT


I want to subscribe to the "iot-2/evt/status/fmt/json" topic with ESP8266 on IBM Watson IOT. The connection is established but it is disconnecting again. So, reconnecting the MQTT client to … and subscribe to iot-2 / cmd / + / fmt / + OK. This cycle continues. Why is the connection broken?

My ESP8266 code is as follows.

I used an ESP8266-12E NodeMCU, I’ve created an Android app for the publisher.

/*
 Basic ESP8266 MQTT example

 This sketch demonstrates the capabilities of the pubsub library in combination
 with the ESP8266 board/library.

 It connects to an MQTT server then:
  - publishes "hello world" to the topic "outTopic" every two seconds
  - subscribes to the topic "inTopic", printing out any messages
    it receives. NB - it assumes the received payloads are strings not binary
  - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
    else switch it off

 It will reconnect to the server if the connection is lost using a blocking
 reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
 achieve the same result without blocking the main loop.

 To install the ESP8266 board, (using Arduino 1.6.4+):
  - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
       http://arduino.esp8266.com/stable/package_esp8266com_index.json
  - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
  - Select your ESP8266 in "Tools -> Board"

*/

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
//#include <ESP8266HTTPClient.h>

#include <SPI.h>
#include <ArduinoJson.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.
//ZYxel
#define ssid  "......."
#define password  ".................."

//GES ARGE
#define ssid2     "..............."      // WiFi SSID
#define password2  "............."  // WiFi password

#define spi_ss_pin SS

#define ORG "............"
#define DEVICE_TYPE "........."
#define DEVICE_ID "..........."
#define TOKEN "................"
//-------- Customise the above values --------
char server[] = ORG ".messaging.internetofthings.ibmcloud.com";
int mqttPort=1883;
const char topic[] = "iot-2/cmd/status/fmt/json"; //"iot-2/cmd/status/fmt/json";

char authMethod[] = "use-token-auth";
char token[] = TOKEN;
char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID;

WiFiClient wifiClient;
void callback(char* topic, byte* payload, unsigned int payloadLength) ;
PubSubClient client(server, 1883, callback, wifiClient);

void setup() {
  Serial.begin(115200);
  Serial.println();
  wifiConnect();
  mqttConnect();
}

void loop() {
  if (!client.loop()) {
    mqttConnect();
  }
}

void wifiConnect() {
  Serial.print("Connecting to "); Serial.print(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.print("nWiFi connected, IP address: "); Serial.println(WiFi.localIP());
}

void mqttConnect() {
  if (!client.connected()) {
    Serial.print("Reconnecting MQTT client to "); Serial.println(server);
    while (!client.connect(clientId, authMethod, token)) {
      Serial.print(".");
      delay(500);
    }
    initManagedDevice();
    Serial.println();
  }
}

void initManagedDevice() {
  if (client.subscribe(topic)) {
    Serial.println("subscribe to cmd OK");
  } else {
    Serial.println("subscribe to cmd FAILED");
  }
}

void callback(char* topic, byte* payload, unsigned int payloadLength) {
  Serial.print("callback invoked for topic: "); Serial.println(topic);

  for (int i = 0; i < payloadLength; i++) {
    Serial.print((char)payload[i]);
  }
}

Solution

  • A device ("use-token-auth" authentication type) cannot subscribe to a topic like "iot-2/evt/status/fmt/json" only "iot-2/cmd/status/fmt/json" is allowed.

    What you need to do is to generate an API key and token and authenticate as an application:

    The following example shows a typical API key:

    a-orgId-a84ps90Ajs

    The following example shows a typical authentication token:

    MP$08VKz!8rXwnR-Q*

    When you make an MQTT connection by using an API key, ensure that the following guidelines are applied:

    The MQTT client ID is in the format: a:orgId:appId
    The MQTT user name is the API key (for example, a-orgId-a84ps90Ajs)
    The MQTT password is the authentication token (for example, MP$08VKz!8rXwnR-Q*)
    

    After that you can subscribe to topic like iot-2/type/device_type/id/device_id/evt/event_id/fmt/format_string. So it should be:

    iot-2/type/yourDeviceType/id/yourDeviceId/evt/status/fmt/json

    You can use the same for commands: this how the topic should look like iot-2/type/device_type/id/device_id/cmd/command_id/fmt/format_string