できること

第66回 ArduinoとSakura.ioで気軽にIoTデバイスを作ってみる – 通信モジュールでいざ通信!

IMG_20170918_144946

前回の記事で、sakura.ioで通信モジュールやArduinoなどのすべての準備ができました。今回はサンプルプログラムを動作させるところからはじめて、実際に通信してみます。

今回の電子工作レシピ

完成までの時間目安:60分
必要なパーツ

目次

  1. 通信モジュールからデータをsakura.ioに送信
  2. sakura.ioから通信モジュールにデータを送信
  3. まとめ

 

1.通信モジュールからデータをsakura.ioに送信

前回、ライブラリをインストールしたので、さっそくサンプルプログラムを動作させてみます。「スケッチ例」-「SakuraIO」-「Shell」を選択して基本的な手動でデータを送信するプログラムを動かしてみます。

d1f1709a41b165de509c23ad43ed2f22
SakuraIOのサンプルプログラム

 


#include <SakuraIO.h>
#include "ntshell.h"
#include "commands.h"

static int func_read(char *buf, int cnt, void *extobj);
static int func_write(const char *buf, int cnt, void *extobj);
static int func_callback(const char *text, void *extobj);
static int ntopt_callback(int argc, char **argv, void *extobj);
static void ntshell_poll(ntshell_t *p);

ntshell_t ntshell;

cmd_list_t cmd_list[] = {
 {(char*)"version", cmd_version},
 {(char*)"serial", cmd_serial},
 {(char*)"status", cmd_status},
 {(char*)"sqi", cmd_sqi},
 {(char*)"unixtime", cmd_unixtime},
 {(char*)"update", cmd_update},
 {(char*)"reset", cmd_reset},
 {(char*)"enqueue", cmd_enqueue},
 {(char*)"sendnow", cmd_sendnow},
 {(char*)"send", cmd_send},
 {(char*)"size", cmd_size},
 {(char*)"cleartx", cmd_cleartx},
 {(char*)"dequeue", cmd_dequeue},
 {(char*)"peek", cmd_peek},
 {(char*)"clearrx", cmd_clearrx},
 {(char*)"file", cmd_file},
 {NULL, NULL}
};

//SakuraIO_SPI sakuraio(10);
SakuraIO_I2C sakuraio;

void setup() {
 Serial.begin(9600);
 Serial.println("Hello");
 Serial.print(">");
 ntshell_init(&ntshell, func_read, func_write, func_callback, (void *)&ntshell);
 ntshell_set_prompt(&ntshell, ">");
}

void loop() {
 ntshell_poll(&ntshell);
}


/* NT-Shell */
static int func_read(char *buf, int cnt, void *extobj) {
 if (Serial.available())
 return Serial.readBytes(buf, cnt);
 else
 return 0;
}

static int func_write(const char *buf, int cnt, void *extobj) {
 return Serial.write(buf, cnt);
}

static int func_callback(const char *text, void *extobj) {
 return ntopt_parse((const char *)text, ntopt_callback, extobj);
}

static int ntopt_callback(int argc, char **argv, void *extobj){
 if (argc == 0) {
 return 0;
 }

 int execnt = 0;
 const cmd_list_t *p = cmd_list;
 while (p->command != NULL) {
 if (ntlibc_strcmp((const char *)argv[0], p->command) == 0) {
 p->func(argc, argv);
 execnt++;
 }
 p++;
 }
 if (execnt == 0) {
 Serial.println("unknown command");
 }

 return 0;
}


static void ntshell_poll(ntshell_t *p)
{
 if (p->initcode != INITCODE) {
 return;
 }
 unsigned char ch;
 if(SERIAL_READ(p, (char *)&ch, sizeof(ch)) > 0)
 vtrecv_execute(&(p->vtrecv), &ch, sizeof(ch));
}

 

プログラムを書き込んだ後に、シリアルモニタを開きます。シリアルモニタの設定は「9600 bps」で改行コードは「CRのみ」に設定します。

e2bed547e873dacbe1579be069cf9f28シリアルモニタの準備

 

シリアルモニタの準備ができたら、データの受信を確認する画面をsakura.ioの管理画面から表示します。前回登録した連携サービスをクリックすると、詳細画面が表示されます。

65f2b6ba8fe57ccb596aeddcd9108f202連携サービスの選択

 

76e280e09a8125986685e9d5455ff22c_2連携サービス詳細画面

 

この画面を開いたままで、シリアルモニタに戻ります。

シリアルモニタで「enqueue 0 i 5656」と入力します。

enqueue – 送信キューにデータを格納するコマンド

enqueueの後ろは「0-チャンネル番号、i-送信するデータの型、5656-送信データの内容」となります。

99e2d6e01d1354e2086b67cd1e2978abenqueueコマンドを入力

 

enqueueコマンドを入力するとシリアルモニタに表示されます。次に送信キューにためたデータを実際にsakura.ioに送るために「send」コマンドを入力します。

send – 送信キューにたまったデータをsakura.ioに送信する

 

a24ceffe32f38c57edf706471496e81e
sendコマンドを入力

f30e87844c2e8154979c7e353ee2aff1「送信」でsendコマンドを送信

 

sendコマンドでデータを送信すると、管理画面上にデータが届いたことが確認できれば無事送信が完了です!

76e280e09a8125986685e9d5455ff22c_3
Arduinoに載せた通信モジュールからデータがsakura.ioに届いている画面

 

これで、通信モジュールからsakura.ioへの簡単なデータの送信方法が確認できました。

 

sakura.ioに届いたデータの利用方法

実際に利用するには、このsakura.ioに届いたデータを上記「サービス連携の編集 WebSocket」の画面の上にあるURLやTokenを使って、別のサーバープログラムからアクセスしてデータを取得したりするようなプログラムを作っていく流れになります。

それらの流れはAPIドキュメントを見ると知ることができます。

 

2.sakura.ioから通信モジュールにデータを送信

Arduino側の通信モジュールからsakura.ioにデータが送ることができたので、次に逆のsakura.ioからArduino側の通信モジュールにデータを送信する方法を試してみます。

2-1.Incoming Webhookの設定

今回の通信方式はIncoming Webhookを利用します。その前に、Incoming Webhookとは何でしょうか?まずwebhookを簡単に説明すると「アプリなどの更新情報を他のアプリへリアルタイムに通知する仕組みや概念」となります。そしてその通知する仕組みはPOST方式で実行されます。

sakura.ioでIncoming Webhookを使うために、管理画面から連携サービスを登録します。連携サービス「サービス追加」よりWebSocketを追加したときのように追加画面に進みます。

138e2431e6bb98e455717983e5ea9747_2
「サービス追加」を選択

 

webs3
Incoming Webhookを選択

 

Incoming Webhookでは、名前とSecretの2箇所設定する必要があります。Secretは接続する際に必要なSecretキーを設定することができるのですが、今回は名前のみで設定しないで進みます。

878e8da6a90192d0a71c2098a5dc5e48
Incoming Webhookの登録画面

 

登録が完了したら、同じように連携サービスのIncoming Webhookの詳細画面を開きます。詳細画面では設定した名前とSecretのほかにTokenとURLという記載が表示されています。

webhookIncoming Webhookの詳細画面

 

URLには/v1/以降にTokenが表示されていると思いますが、このURLにPOSTデータを送信することで通信モジュールにデータを送ることができます

 

2-2.サーバ側のプログラムを用意する

今回のIncoming Webhookの一連の流れは下記の図になります。今回はサーバ側にプログラムを用意して、それをブラウザでアクセスした際に通知するようにしていますが、「ブラウザでアクセス」というのを、別のアプリやシステムに置き換えれば一般的なWebhookとして「他のアプリからの通知を通信モジュールに送信する」という利用が可能になります。

今回このIncoming Webhookを利用している例としてさくらインターネットさんの「さくらのナレッジ」のウェブサイトに「さくらのIoT Platformで、”ヤバい状況であることを光って知らせる装置”をできるだけ安価に作ったお話」一連の実装について紹介例がありますので、今回そのコードを参考に進めていきます。

webhook4今回のIncoming Webhookでの通知の流れ

 

サーバ側はPHPを利用します。PHPプログラムはそれぞれPHPが動作可能なサーバなどに設置してください。下記プログラムのモジュールのIDは管理画面の一覧に表示されているIDを設定します(通信モジュールに書かれているIDではありませんので注意)。tokenは連携サービスに記載されているtokenを設定します。


<?php $digit = htmlspecialchars($_GET["val"], ENT_QUOTES, 'UTF-8'); $module = "[モジュールのIDを記載]"; $token = "[tokenを記載]"; $secret = ""; function send_to_iot($token, $payload, $secret){ $webhook_url = "https://api.sakura.io/incoming/v1/{$token}"; $x_sakura_signature = hash_hmac("sha1", $payload, $secret); $headers = array( 'Content-Type: application/json', 'Accept: application/json', 'X-Sakura-Signature: '. $x_sakura_signature, ); $options = array( 'http' => array(
'method' => 'POST',
'header' => implode("\r\n", $headers),
'content' => $payload,
)
);
$response = file_get_contents($webhook_url, false, stream_context_create($options));
return $response === 'ok';
}

$data = array(
'type' => 'channels',
'module' => $module,
'payload' => array(
'channels' => array( array(
'channel' => 0,
'type' => 'i',
'value' => intval($digit),
)
)
)
);
$payload = json_encode($data);
send_to_iot($token, $payload, $secret);

サーバーに設置して下記のように?val=1などとvalのあとに0~9の数値を設定すると通信モジュールに通知されるような仕様になっています。(送信する内容は0~9以外でもよいですが、今回Arduino側で1桁のint型を受けるようにしています)

https://xxx.xxx.xxx/incoming_webhook.php?val=1

 

2-3.Arduino側のプログラム

次にArduino側のプログラムを用意します。こちらもさくらのナレッジで紹介されている例をもとに今回用に書き換えをしています。主な処理の流れは、sakura.ioからgetRxQueueLength関数で受信できるデータがあるかどうかを確認したのち、データがあればdequeueRx関数で取得して、その内容に合わせて2のLEDを光らせる処理を実施する、という流れになっています。

今回13番ピンにLEDを接続して光らせる・消すという処理を書いていますので、LEDをつけてみてください(LEDがなくてもArduino本体のLEDがついたり消えたりします)


#include <SakuraIO.h>

SakuraIO_I2C sakuraio;
#define LED 13
int cnt = 0;

void setup() {
delay(1000);
Serial.begin(9600);
Serial.print("Waiting to come online");
for (;;) {
if ( (sakuraio.getConnectionStatus() & 0x80) == 0x80 ) break;
Serial.print(".");
delay(1000);
}
Serial.println("");
pinMode(LED, OUTPUT);
}

void loop() {
uint8_t available;
uint8_t queued;
boolean signal_flg;
boolean blink_flg;
cnt++;
Serial.print("Count :");
Serial.print(cnt);
available = 0;

//************************************************************
//* 1.sakura.ioからデータを取得
//************************************************************
if (sakuraio.getRxQueueLength(&available, &queued) != CMD_ERROR_NONE) {
Serial.println("[ERR] get rx queue length error");
}

if (available > 0){
uint8_t ch, type, value[8];
int64_t offset;
sakuraio.dequeueRx(&ch, &type, value, &offset);
Serial.print(" Value :");
Serial.println(value[0]);
if (value[0] == 1) {
signal_flg = 1;
}else{
signal_flg = 0;
}
}

//************************************************************
//* 2.取得したデータをもとにLEDを光らせる
//************************************************************
if(signal_flg == 1){
//1-光らせる
digitalWrite(LED, HIGH);
blink_flg = 1;
}else{
//0-消す
digitalWrite(LED, LOW);
blink_flg = 0;
}
sakuraio.clearRx();
delay(1000);
}

 

実際にArduinoに書き込み、シリアルモニタを表示した状態で先ほどのサーバ側プログラムにval=1やval=0としてアクセスすると、ブラウザ上は真っ白なページが表示されるだけ。変化はありませんが、シリアルモニタに下記のように数値の変化が見られ、Arduino側に接続された通信モジュールに正常に値を送信できていることが確認できますね!

5fb752879e99b712b53bc09dad672280
Incoming Webhookでデータを受信

 

サーバ側プログラムを修正して、ON(val=1)/OFF(val=0)を切り替えるようにしてみました。

 

これで、手軽に外部からsakura.ioを通じてArduinoを制御することができますね!

 

まとめ

sakura.ioを使って実際に通信することができました!次回はさらにスマートフォンやほかのアプリから通信モジュールを通じてArduinoを制御するデバイスの作成に取り組んでみたいと思います!

 

アバター画像

電子工作や新しいデバイスをこよなく愛するエンジニア。日常生活のちょっとしたことを電子工作で作って試して、おもしろく過ごしたいと日々考えています。

高専ロボコン2015 出場ロボット解剖計画