目次
はじめに
鶴渕一成と申します。IoTについていろいろ勉強しています。収穫があったら随時ここに寄稿したいと考えています。
さて、WiFi付き、切手大、センサーハブ ESP-WROOM-02 はとても安価です。モジュール自体は600円位、各端子に接続しやすいように基板にはんだ付けされたもので1000円位とお父さんのお小遣い程度で買えてしまいます。
センサーハブが安ければ、そして小さければ、それを使ってIoTが爆発的に普及するかもしれません。
このセンサーハブを使いこなせるようにしておけば、技術者として引く手あまたなはず!?
ESP-WROOM-02からデータをインターネットに送信するという方法はいくつかネット上に載っていますが、受信する方法はあまりネット上に載っていません。
なので、この記事は多分重宝されるはずです。
受信方法を習得できれば、ブラウザを使って自宅のエアコンをオンオフ出来たりも夢じゃない!!
今回作るもの
ブラウザからコマンドを送って、ESP-WROOM-02に接続したLEDを、点灯させたり、消灯させたりする仕組みを作ります。
前提
以下は、この記事を読むに当たっての前提です。
最低限ここまでは出来ているという前提で話を進めていきます。
前提を満たすための参考リンクだけは出来るだけ載せておきます。
この辺を詳しく書いてほしいという要望があれば言ってください。
- Arduino-IDE(ESP-WROOM-02用プログラム開発環境)のインストール。
【参考】Check! ESP-WROOM-02 開発ボードの始め方 - ESP-WROOM-02にプログラムを書き込む準備
【参考】Check! IoT ができるようになるまで ~ ESP-WROOM-02 にプログラムを焼く - ESP-WROOM-02にLEDを接続
【参考】初めてのESP8266(REESPUSB) Lチカまでの最短ルートとハマリポイント - ESP-WROOM-02をBluemixのInternet of Things platform サービスに登録。
- Node-RED stater サービスの開始。
- 登録したESP-WROOM-02をBluemixのNode-RED stater サービスに接続。
【参考】Check! IoT ができるようになるまで ~ ESP-WROOM-02 を IoT Foundation で Bluemix につなぐ!
ESP-WROOM-02のプログラムの準備
ESP-WROOM-02のプログラムは、Arduinoで書きます。他にもpythonとか使えるらしいのですが、個人的にライブラリが揃っているのでArduinoを愛用しています。
Arduinoはc++をベースにした言語らしいので、必要な場合はC++を勉強するといいはずです。
ソースコードを1行ずつ解説すると長くなってしまうので、ポイントだけを説明し最後にソースコード全体を載せようかと思います。
ソースコードはサンプルや、JSON関連はサンプル参考にしました。
ポイント1 Bluemixとの接続周り
Bluemixとの接続と、Subscribeの指定は、95~108行目で以下のように行っています。
Bluemixと接続してなければ接続するまで接続操作を繰り返し、接続したらSubscribeの設定を行います。
18~29行目に格納された接続用の値を駆使して、接続操作を行います。
if (!!!client.connected()) {
Serial.print("Reconnecting client to ");
Serial.println(server);
while (!client.connect(clientId, authMethod, token)) {
Serial.print(".");
delay(500);
}
if (client.subscribe(subtopic)) {
Serial.println("Subscribe ok");
} else {
Serial.println("Subscribe failed");
}
Serial.println();
}
ポイント2 受信時の動きを関数で記述
Subscribeでデータを受け取った時の処理を関数で記述し、データを受け取った時に起動させる関数をsetCallbackファンクションで指定します。
ソースでは34行目でcallbackという関数を宣言しています。なおこの例では関数の中で受け取ったJsonデータをパースし、要素「cmd」の値を取り出しています。
さらに要素「cmd」の値が「on」の場合、LEDの接続されたピンをHIGH、すなわちLEDを点灯させます。
void callback(char* topic, byte* payload, unsigned int length) {
....
}
89行目で、callbackという名前の関数をデータを受け取った時に起動させる関数として指定しています。
client.setCallback(callback);
ポイント3 受信処理コマンドの記述
これは重要です。受信処理コマンドを忘れるとセンサーハブがデータを受け取ってくれません。loopファンクションを使います。
私はサンプルソースを見てもこれに気づかずデータが受信できず数日間ハマりました。
ソースの110行目を参考にしてください。
client.loop();
ソース全体
c:LED_on_off.ino
/*
This source code refer to the recipe of IBM developerWorks, https://developer.ibm.com/recipes/tutorials/connect-an-esp8266-with-the-arduino-sdk-to-the-ibm-iot-foundation/ .
*/
//Subscribeの cmd の値が on ならLEDをオンする。
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <string.h>
//LEDは ピン16
const int ledpin = 16;
//-------- Customise these values -----------
const char* ssid = "xxxxx";
const char* password = "xxxxx";
#define ORG "xxxxxx" // 組織ID
#define DEVICE_TYPE "ESP8266" // デバイス・タイプ
#define DEVICE_ID "ESP8266_001" // デバイスID
#define TOKEN "xxxxxxxxxxxxxxx" // 認証トークン
//-------- Customise the above values --------
char server[] = ORG ".messaging.internetofthings.ibmcloud.com";
//char topic[] = "iot-2/evt/status/fmt/json";
char subtopic[] = "iot-2/cmd/cid/fmt/json";
char authMethod[] = "use-token-auth";
char token[] = TOKEN;
char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID;
WiFiClient wifiClient;
PubSubClient client(wifiClient);
void callback(char* topic, byte* payload, unsigned int length) {
Serial.println("Subscribed Message Receaved");
char message[200];
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
message[i] = (char)payload[i];
}
Serial.println();
Serial.println(message);
// JSON parse
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(message);
if (!root.success())
{
Serial.println("parseObject() failed");
return;
}
const char* cmd = root["cmd"];
Serial.println(cmd);
if(strcmp(cmd, "on") == 0) {
digitalWrite(ledpin, HIGH);
}
else {
digitalWrite(ledpin, LOW);
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println();
Serial.print("Connecting to ");
Serial.print(ssid);
WiFi.begin(ssid, password);
// initialize digital pin 16 as an output.
pinMode(ledpin, OUTPUT);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("WiFi connected, IP address: ");
Serial.println(WiFi.localIP());
client.setServer(server, 1883);
client.setCallback(callback);
}
void loop() {
// put your main code here, to run repeatedly:
if (!!!client.connected()) {
Serial.print("Reconnecting client to ");
Serial.println(server);
while (!client.connect(clientId, authMethod, token)) {
Serial.print(".");
delay(500);
}
if (client.subscribe(subtopic)) {
Serial.println("Subscribe ok");
} else {
Serial.println("Subscribe failed");
}
Serial.println();
}
client.loop();
delay(10000);
}
Bluemix側
全体
Node-Redフローエディタで全体は以下の通りです。これ以降各ボックスの詳細を掲載します。
http_input([get]/test)
メソッドはGETを選びます。URLはここでは/testとしておきます。
ボックス | ボックスの詳細 |
---|---|
http_output(http)
このボックスは詳細設定の必要はありません。
ボックス | ボックスの詳細 |
---|---|
switch
payload.onoffの値(ブラウザから渡された要素「onoff」の値)が「on」だったら上から1番目のルート、「off」だったら上から2番目のルートに進むよう設定しています。
ボックス | ボックスの詳細 |
---|---|
Function1(test command on)
ここでは、ESP-WROOM-02へ送信するデータを作っています。要素 msg.payload.cmd の値にon、要素 msg.deviceIdの値にAccess-techinica_001をセットしています。cmsgというJSONデータを作っているんですが、どうもこのボックスを出るときにcmsgというJSONデータはmsgというデータに名前を変えるみたい。事実、次のボックスではmsgという名前のJSONデータに要素も値も引き継がれています。
ボックス | ボックスの詳細 |
---|---|
Function2(test command off)
ここでも、ESP-WROOM-02へ送信するデータを作っています。要素 msg.payload.cmd の値にoff、要素 msg.deviceIdの値にAccess-techinica_001をセットしています。
ボックス | ボックスの詳細 |
---|---|
IoTout(IBM IoT App Out)
ESP-WROOM-02にデータを送り出す設定です。Device TypeとDevice idの2つの値で、どのセンサーにデータを送り出すかを識別しています。この2つの値は、センサーの方に書き込むソースのDevice TypeとDevice idの値と合わせてください。
この記事でのソースでは、
要素 | 値 |
---|---|
Device Type | ESP8266 |
Device id | ESP8266_001 |
と設定してあります。
(ソースの19・20行目参照)
ボックス | ボックスの詳細 |
---|---|
いざ実行
ブラウザのURL欄に
http://[経路URL]/test?[要素名]=[値]
例)http://tajima-iot.eu-gb.mybluemix.net/test?onoff=on
と打ち込みます。
「/test」というのは、Node-REDのhttp_inputボックスのURL欄に指定したものです。
また、[経路URL]はダッシュボードの「経路」に示されたURLです。またはNode-REDフローエディタのURLだと思ってください。
http://[経路URL]/test?onoff=on とブラウザのURL欄に入力すると
http://[経路URL]/test?onoff=off とブラウザのURL欄に入力すると
このようにLEDが点灯したり消灯したりすれば成功です。??