Anthony Elder published a guide on developerWorks Recipes on how to “Build your own Watson controlled kettle” for ESP8266. This article’s code is shamelessly ripped-off from him for broader usage. This guide will show how to turn on and turn off a LED connected with ESP32 Arduino from IBM Watson IoT platform. That “remote control” over the internet will be shown by using a simple bash scripts – you can use it from Android Smartphone with Terminal app. You can use a relay with ESP32 instead of LED. Anthony Elder’s work solved the opposite direction of command. Normally, we are used with sending data from ESP32 attached pushbutton or ESP32 attached sensors like DHT11 to IBM Watson IoT. But with this guide, you can control a LED attached with ESP32 from smartphone located anywhere on this earth. If we combine both, then that becomes two-way communication.
I will suggest reading Anthony Elder’s original idea to realize the meaning of the code :
1 2 3 | # https://developer.ibm.com/recipes/tutorials/build-your-own-watson-controlled-kettle/ # |
As he had a physical button too, there is a button code too. It is a great feature as template code. I am going to back-version of his development for a general purpose need. In IBM Watson IoT platform, as usually keep TLS connection as optional. Generate a new API key for your device :
---
1 2 3 | # https://developer.ibm.com/tutorials/iot-generate-apikey-apitoken/ # |
The API key is mentioned as
elsewhere in IBM’s documentation.
The Auth token is mentioned as
elsewhere in IBM’s documentation.
Copy-paste them in a safe place. You will need both for constructing the cURL command to turn on and off from bash script. Normally, we will need the auth token in the code for ESP32.
The above thing is the difference with the other guides.
Required Hardware to Test ESP32 Arduino LED Controlled from IBM Watson IoT
For testing propose, only ESP32 will be sufficient. It will be great if you can add three LEDs to Pin 19, Pin 18
and some other pin like Pin 4. We need to check the pin which is defined in DEVICE_RELAY
in the code. That is Pin 19 in our code. We suggest to use :
Pin 19 = Yellow LED
Pin 18 = Green LED
Pin 4 = Red LED
Pin 4 and Pin 12 may not work on ESP32! Why that is written here :
1 2 3 | # https://github.com/espressif/arduino-esp32/issues/1204 # |
How funny! The dimension of ESP32 is so odd on a breadboard that I was forced to use the pins of one side. Pin 5 is of the power LED. Pin 2 is onboard LED. During testing the code, I saw that the red LED not glowing ever. As it is not too important for the main goal, I ignored it & pushed the code on GitHub with pin 4. It is a slight China electronics issue. You can use Pin 2 instead of Pin 4.
We have the complete project on GitHub repo. Here is the code for ESP32 Arduino :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | #include <WiFi.h> #include <PubSubClient.h> #include <Ticker.h> #include <HTTPClient.h> #include <SPI.h> const char* ssid = "yourNetworkName"; const char* password = "yourNetworkPass"; //-------- Customise these values ----------- #define ORG "change" #define DEVICE_TYPE "change" #define DEVICE_ID "change" #define TOKEN "change" //-------- Customise the above values -------- #define DEVICE_BUTTON 0 #define DEVICE_RELAY 19 #define DEVICE_GREEN_LED 18 #define DEVICE_RED_LED 4 Ticker ledBlinker; char server[] = ORG ".messaging.internetofthings.ibmcloud.com"; char authMethod[] = "use-token-auth"; char token[] = TOKEN; char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID; #define CMD_STATE "/gpio/" // use the '+' wildcard so it subscribes to any command with any message format const char commandTopic[] = "iot-2/cmd/+/fmt/+"; void gotMsg(char* topic, byte* payload, unsigned int payloadLength); WiFiClient wifiClient; PubSubClient client(server, 1883, gotMsg, wifiClient); int buttonPressDuration; void setup() { Serial.begin(115200); Serial.println(); pinMode(DEVICE_RELAY, OUTPUT); pinMode(DEVICE_GREEN_LED, OUTPUT); pinMode(DEVICE_RED_LED, OUTPUT); ledBlinker.attach(0.1, ledBlink); // fast blink indicates Wifi connecting wifiConnect(); ledBlinker.attach(0.4, ledBlink); // slower blink indicates MQTT connecting mqttConnect(); ledBlinker.detach(); digitalWrite(DEVICE_GREEN_LED, LOW); // low is led on to show connected pinMode(DEVICE_BUTTON, INPUT); attachInterrupt(DEVICE_BUTTON, buttonPress, CHANGE); } int lastHeartBeat; void loop() { if (buttonPressDuration > 0) { doCommand(digitalRead(DEVICE_RELAY) ? "off" : "on"); buttonPressDuration = 0; } if (!client.loop()) { mqttConnect(); } if (millis()-lastHeartBeat > 10000) { Serial.print("loop: gpio "); Serial.print(DEVICE_RELAY); Serial.print(" current state "); Serial.println(digitalRead(DEVICE_RELAY) ? "On" : "Off"); digitalWrite(DEVICE_GREEN_LED, HIGH); // flicker LED to show its active delay(200); digitalWrite(DEVICE_GREEN_LED, LOW); lastHeartBeat = millis(); } } void gotMsg(char* topic, byte* payload, unsigned int payloadLength) { Serial.print("gotMsg: invoked for topic: "); Serial.println(topic); if (String(topic).indexOf(CMD_STATE) > 0) { String cmd = ""; for (int i=0; i<payloadLength; i++) { cmd += (char)payload[i]; } doCommand(cmd); } else { Serial.print("gotMsg: unexpected topic: "); Serial.println(topic); } } void doCommand(String cmd) { int currentState = digitalRead(DEVICE_RELAY); int newState = (cmd == "on"); digitalWrite(DEVICE_RELAY, newState); Serial.print("Relay switched from "); Serial.print(currentState ? "On" : "Off");Serial.print(" to "); Serial.println(newState ? "On" : "Off"); } unsigned long startPress = 0; void buttonPress() { int currentState = digitalRead(DEVICE_BUTTON); if (currentState == 0) { // 0 is pressed, 1 is released startPress = millis(); } else { int diff = millis() - startPress; if (diff > 100) { // debounce buttonPressDuration = diff; } } Serial.print("Button "); Serial.print(currentState ? "released" : "pressed"); Serial.print(" duration="); Serial.println(buttonPressDuration); } void ledBlink() { digitalWrite(DEVICE_GREEN_LED, ! digitalRead(DEVICE_GREEN_LED)); } 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); } Serial.println(); } subscribeTo(commandTopic); } void subscribeTo(const char* topic) { Serial.print("subscribe to "); Serial.print(topic); if (client.subscribe(topic)) { Serial.println(" OK"); } else { Serial.println(" FAILED"); } } |
You can use cURL to test sending the commands:
1 | curl -u <use-the-API-Key>:<use-auth-token> -H "Content-Type: text/plain" -v -X POST http://<your org>.messaging.internetofthings.ibmcloud.com:1883/api/v0002/application/types/<yourDeviceType>/devices/<yourDeviceId>/commands/gpio -d "on" |
I have written two easy bash scripts to turn ON :
1 2 3 4 5 6 7 8 9 | #!/bin/bash CURL='/usr/bin/curl' curl -u <use-the-API-Key>:<use-auth-token> -H "Content-Type: text/plain" -v -X POST http://<your org>.messaging.internetofthings.ibmcloud.com:1883/api/v0002/application/types/<yourDeviceType>/devices/<yourDeviceId>/commands/gpio -d "on" # or you can redirect it into a file: # $CURL > watson.log |
and to turn OFF :
1 2 3 4 5 6 7 8 9 | #!/bin/bash CURL='/usr/bin/curl' curl -u <use-the-API-Key>:<use-auth-token> -H "Content-Type: text/plain" -v -X POST http://<your org>.messaging.internetofthings.ibmcloud.com:1883/api/v0002/application/types/<yourDeviceType>/devices/<yourDeviceId>/commands/gpio -d "off" # or you can redirect it into a file: # $CURL > watson.log |
Save them with file names such as watson-on-sh
and watson-off.sh
, CHMOD them :
1 2 | chmod +X watson-on.sh chmod +X Watson-off.sh |
Execute them on need :
1 2 | sh watson-on.sh sh Watson-off.sh |
You can do it from a computer, as well as a terminal app on an Android device. Now, Anthony Elder’s project became “ESP32 and mobile compatible”! Obviously, do it with many kinds of stuff at home you have to develop a real Android application. This ends this guide.
Tagged With Anthony Elder esp32 now , how to turn on led from other computer with esp32 , internet controlled leds using esp32 , watson iot esp32