概要
IoTはモノとモノがつながる世界!
ということで「インターネット経由でデバイスがデバイスを動かす」を試してみます。具体的にはWiFi接続された2つのESP8266を用いて、IoTプラットフォームThingSpeak を介し、片方がもう一方を動作させる方法を紹介します。インターネット経由なので、各々Wi-Fi接続されていれば、一方が地球の反対にあっても同じ動作をします。
これは磁気スイッチの開閉を検知して、離れた場所でLチカ(開くとON)するシンプルな例ですが、入出力は様々なものに置き換えて応用できます。
デバイスの遠隔操作というと難しそうなイメージがあるかもしれませんが、今回はThingSpeakのTalkBackという機能を利用し、各デバイスではコマンドの「書き換え」と「読み取り」のみの簡単なコーディングで連携できます。
もくじ
1. 準備
2. ThingSpeakのTalkBack設定
3. 磁気スイッチON/OFFデータを収集する(コマンドの書き換え)
4. TalkBackのコマンドに連動してLチカさせる(コマンドの読み取り)
5. まとめ
1. 準備
■ハードウェア
●ESPr® One ×2 https://www.switch-science.com/catalog/2620/
●リードスイッチ(磁石付セット) http://akizukidenshi.com/catalog/g/gP-04025/
●その他(LED,抵抗,ジャンパワイヤ、USBmicroケーブル等)
■開発環境
Arduino IDE (作成時は1.6.5を利用)
■ThingSpeakのアカウント、Channel作成
IoT プラットフォーム ThingSpeak
https://thingspeak.com/
ThingSpeakは無料で使い始めることができるIoTプラットフォームで、「データ収集と可視化」「解析」「アクション」の機能を持っています。
ThingSpeakの基本的な使い方は、こちらでわかりやすくまとめられています。
データを簡単に保存&グラフ化できるThingSpeakが便利!
http://iwathi3.hatenablog.com/entry/Data-to-Graph-ThingSpeak
データロギングに使うChannel IDとWrite API Keyをメモっておきます。
2. ThingSpeakのTalkBack設定
TalkBackの作成
ThingSpeakの[Apps]→[TalkBack]をクリックします。
つづいて[New TalkBack]をクリックします。
次にTalkBackの名前と[Add a new Command]をクリックし、Command Stringに「SW_OFF」と入力します。これは事前にCommand IDを取得するのが目的なので、このCommand Stringはデバイスから書き換えて利用します。入力が終わったら[Save TalkBack]を押します。
TalkBack ID / API Key / Command IDの確認
表示されている①TalkBack ID ②(TalkBackの)API Key ③Command IDを控えておきます。
3. 磁気スイッチON/OFFデータを収集する(コマンドの書き込み)
データ収集デバイスのコーディング
準備ができたら、デバイス連携を行います。まずはデータ収集とコマンドの書き換えから。
一つ目(データ収集側)のデバイスで行うのは下記です
ESPr® Oneの入力PinはIO2を利用し、磁気スイッチの他方のリードはGNDに接続します。
Pin2をInputモードにし、その状態に応じて「SW_ON」もしくは「SW_OFF」のコマンドをThingSpeakのTalkBackに送ります。磁石が離れているとPin2はHighになります。 下記のサンプルではputTalkBack()でコマンドの書き換え、writefield()でChannelへのデータロギングを行っています。
コマンドの書き換えは、Talkbackのページにアップデート方法が書かれているので、この通りにESP8266からコマンドを送ります。
サンプルコード
#include <ESP8266WiFi.h>
char thingSpeakAddress[] = "api.thingspeak.com";
unsigned long myChannelNumber = ******; // Channel ID
String myWriteAPIKey = "****************"; // Channel Write API Key
String talkBackID = "*****"; // TalkBack ID
String talkBackAPIKey = "****************"; // TalkBack API Key
String COMMAND_ID ="*******"; // TalkBackで作成したCommand ID
String url = "/talkbacks/"+talkBackID+"/commands/"+COMMAND_ID;
const char* host = "api.thingspeak.com";
String magsw ="0";
char ssid[] = "******"; // 無線LANのSSID
char pass[] = "******"; // 無線LANのpassword
int status = WL_IDLE_STATUS;
WiFiClient client;
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, pass); // WiFi接続
pinMode(2, INPUT); // IO2を入力Pinに設定
}
void loop() {
// スイッチが離れ、IO2がHighになったら
// Channel Fieldへの書き込みとTalkBackのコマンドの書き換えを行う
if (digitalRead(2) == HIGH){
String magsw = "1";
String commandstr = "SW_ON";
writefield(magsw); // Channelへのデータ書き込み
putTalkBack(commandstr); // TalkBackコマンドの変更
}
else{
String magsw = "0";
String commandstr = "SW_OFF";
writefield(magsw);
putTalkBack(commandstr);
}
delay(100); // 無料版使用の場合はChannelへの書き込みは15秒に1回に変更。delay(15000)
}
void putTalkBack(String commandstr)
{
if (client.connect(thingSpeakAddress, 80))
{
Serial.println("Connected to ThingSpeak.");
Serial.println("talkback post: " + commandstr);
String tsData = "api_key="+ talkBackAPIKey +"&command_string="+commandstr;
// talkbackコマンド書き換えのためにhttpコマンド送信
client.print(String("PUT ") + url + "&headers=false" + " HTTP/1.1\r\n"
+ "Host: " + host + "\r\n"
+ "Connection: close\r\n"
+ "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Content-Length: "+tsData.length()+"\n\n"+tsData+"\n\n");
client.stop();
delay(100);
}
else
{
Serial.println("Connection failed.");
}
}
void writefield(String magsw)
{
if (client.connect(thingSpeakAddress, 80))
{
Serial.println("Connected to ThingSpeak for write field.");
Serial.println("write data: " + magsw);
String SWData = "api_key="+ myWriteAPIKey +"&field1="+ magsw;
// Channel fieldへのデータ書き込みのためにhttpコマンド送信
client.print(String("POST /update HTTP/1.1\r\n")
+ "Host: " + host + "\r\n"
+ "Connection: close\r\n"
+ "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Content-Length: "+SWData.length()+"\n\n"+SWData+"\r\n\r\n");
client.stop();
}
else
{
Serial.println("Connection failed.");
}
}
4. TalkBackのコマンドに連動してLチカさせる(コマンドの読み取り)
Lチカするデバイスのコーディング
3ではスイッチの変化でTalkBackのコマンドが定義される状態になりました。
続いてもうひとつの(コマンドに連動しアクションする)デバイスで用意する機能は下記です。
TalkBackのコマンドは下記のようにGET コマンドで読み取ることができます。
ここでも必要なのは①TalkBack ID ②(TalkBackの)API Key ③Command ID
取得ができたら、コマンドに応じて出力Pinの「HIGH」「LOW」を切り替えるだけです。
サンプルコード
#include <ESP8266WiFi.h>
const char* ssid = "***"; // 無線LAN SSID
const char* password = "***"; // 無線LAN password
const char* host = "api.thingspeak.com";
String TalkBackID ="*****"; //Talkback ID
String TalkBackAPIKey ="****************"; // Talkback API key
String Command_ID ="*******"; // Talkbackで作成したコマンドID
// TalkBackコマンド取得のためのURL
String url = "/talkbacks/"+TalkBackID+"/commands/"+Command_ID+"?api_key="+TalkBackAPIKey;
// Use WiFiClient class to create TCP connections
WiFiClient client;
const int ledPin = 13; //Pinの指定IO13
void setup() {
Serial.begin(115200);
delay(100);
// WiFiに接続
Serial.println();
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.print("IP address: ");
Serial.println(WiFi.localIP());
pinMode(ledPin, OUTPUT);
}
void loop() {
Serial.print("connecting to ");
Serial.println(host);
if (client.connect(host, 80)) {
Serial.println("Tcp Connection eastablished with thingSpeak API");
}
else {
Serial.println("connection failed");
return;
}
// 接続が確認されたらTalkBackの現在のコマンドの状態を取得する
client.print(String("GET ") + url + "&headers=false" + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n");
delay(100);
// メッセージの読み取り
String messageBody = "";
while (client.available()) {
String line = client.readStringUntil('\n');
if (line.length() == 1) {
messageBody = client.readStringUntil('\n');
break;
}
}
// コマンドのON/OFFに応じて出力を変更する
Serial.print("Found a message, the message is: ");
if(messageBody == "SW_ON"){
Serial.print(messageBody);
digitalWrite(ledPin, HIGH);
}
if(messageBody == "SW_OFF"){
Serial.print(messageBody);
digitalWrite(ledPin, LOW);
}
client.stop();
Serial.println();
Serial.println("closing connection");
Serial.println();
delay(100);
}
5. まとめ
ThingSpeakのTalkBackを用いて
・HTTPコマンドを投げる
・Lチカ(Pin I/Oの制御)
の基本的な機能で複数のESP8266を連携することができました。
コマンドで管理することで、動かす側、動かされる側それぞれ分けて接続を考えればよく、
Channel Fieldへの結果のロギングも合わせてデバックも非常に簡単になります。
デバイスを3個4個と拡張していくこともできます。