この記事ではSigfoxのサービスを使ってセンサーのデータをクラウドに送るシステム構築の例を示します。前提としてワンボードマイコン(ここではM5Stackを使用)やWEBアプリの知識があることを想定しています。
Sigfoxの概要
LPWAとはLow Power Wide Area-networkの略称で、低消費電力かつ広範囲なエリアでの通信を目的とした無線ネットワーク方式の総称です。”どこかに設置したIOTセンサー” とデータ通信するためにはこのようなネットワークが必須になります。国内でもLPWAサービスがいくつか存在し、目的に応じて事業者を選択しなければなりません。Sigfoxはフランス規格を元に展開されているLPWAサービスのひとつで、1国につき1社のみがサービスできることになっており、日本では京セラ・コミュニケーションシステムが推進しています。
- 通信方式
- 920MHz帯
- 通信速度 100bps
- 通信回数 最大140回/日
- 送信データサイズ 12バイト/回
- 伝送距離 最大50km
- 費用
通信費は1日あたりの通信回数と契約デバイス(回線)数で決まります。Sigfoxデバイスの開発キット(Devkit)は、1年間無償で利用でき、2年目以降は新たに契約が必要です。
- サービスエリア
国内人口カバー率95%とのことですが、上記マップに見られるように山間地などは未整備のようです。未整備地区ではレンタル基地局の利用も検討すべきでしょう。
- Sigfox通信を利用するまでの流れ
- 実装例
M5Stack COM.X Sigfoxの使い方
LPWA(Sigfox)で二酸化炭素濃度を測ってみた
M5Stack COM.X Sigfox モジュールのインストール
M5Stack用のSigfoxモジュール を入手したので手順を示します。M5Stack Core2にも対応していますが、一般的なM5Stack Grayにインストールしました。販売会社のスイッチサイエンスの解説ページは ここ です。
- 品番は M5STACK-M031-F-WA、SigFox用、アンテナ付属
- 2箇所にアンテナ取り付け用の穴があるります。(Reserved)ではない方を使用しました。
- アンテナコネクタは繊細で壊れやすいので慎重に、垂直に嵌め込むこと。なるべく取り外さない方が良いが、どうしても取り外すときには特に注意すること。通常、メーカーでは治具を使って作業します。
- M5Stack Grayの場合は電池モジュールで挟み込む形になる。
- M5Stack Core2に取り付けると背面が基板むき出しになってしまうので何か対策が必要です。
Device ID と PAC を調べる
デバイスを登録するためには Device ID と PAC が必要なので調べます。M5Stackの場合はモジュールに書き込まれているので、それを読み出します。
- Arduino IDE 開発環境(M5Stack Gray/Core2)を参考に、Arduino IDE でスケッチを書き込む環境を作ってください。
- GitHubに登録されているサンプルスケッチ を実行します。
- 下のように表示されます。1行目が Device ID、2行目が PAC です。
デバイスを登録する
開発キットのデバイスの登録は Buy Sigfox Connectivity のページから行います。手順は ここ を参照にしてください。Device ID と PAC の登録については ここ も参照してください。
今回の登録内容は以下の通りです。
Device ID: 12345A00
PAC: XXXXXXXXXX123ABC
Company Name: XXXXXXXXXX
Name: Xxxxxx Xxxxxxxxxx
Email: xxxx@xxx.ac.jp
Password: XXXXXXXX
Expired: 2022/3/4
SigfoxクラウドのDEVICE一覧 にログインするとデバイスの登録状況が見えます。
M5Stackから温湿度データを送信する
M5Stack COM.X Sigfoxの使い方 を参考にM5Stackをプログラミングしていきます。参考ページはあまり実用的ではないので、温湿度センサー DHT11 をM5Stackに接続します。
温湿度センサ DHT11 については、Arduino IDEの [ツール] > [ライブラリを管理] でライブラリマネージャを起動し、”DTH11″ を検索するとAdafruit社のライブラリがありますのでインストールしてください。
先程の参考ページのプログラムを元にDTH11の機能を取り入れたのが下記のソースコードです。
<sigfox-sensor.ino>
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 |
#include <M5Stack.h> #include <DHT.h> // 温湿度センサ DHT11 を5ピンにつなぐ const int PIN_DHT = 5; DHT dht( PIN_DHT, DHT11 ); // float(4バイト)をビット列として扱いたいので // long(4バイト)とのunionを宣言する。 union {float f; long l; } temp, humid; int loopcount = 0; // 4バイトのデータ(long型)を8桁16進文字列に変換する void ltox(long val, char *s) { const char *hex = "0123456789ABCDEF"; s[0] = hex[(val & 0xF0000000) >>28]; s[1] = hex[(val & 0x0F000000) >>24]; s[2] = hex[(val & 0x00F00000) >>20]; s[3] = hex[(val & 0x000F0000) >>16]; s[4] = hex[(val & 0x0000F000) >>12]; s[5] = hex[(val & 0x00000F00) >> 8]; s[6] = hex[(val & 0x000000F0) >> 4]; s[7] = hex[(val & 0x0000000F) ]; } void setup() { M5.begin(true, false, true); M5.Power.begin(); dht.begin(); Serial2.begin(9600, SERIAL_8N1, 16, 17); showTempl(); } void loop() { // クラウドからのデータがあれば受信する // 具体的には、Device IDとPACが返ってくるので表示して少し待つ。 if (Serial2.available()) { M5.Lcd.println(Serial2.readString()); delay(10000); } // ボタンの状態を更新 M5.update(); // Aボタンを押したらデータを送信する。 if (M5.BtnA.wasReleased()) { char data[40] = "AT$SF=........________"; ltox(temp.l, data+6); ltox(humid.l, data+14); M5.Lcd.setTextColor(BLUE); M5.Lcd.setCursor(10, 110); M5.Lcd.println("Data sent."); M5.Lcd.setCursor(10, 128); M5.Lcd.println(data); // 画面表示 Serial2.println(data); // 送信 delay(5000); } // Cボタンを押したらDevice IDとPACを問い合わせる。 else if (M5.BtnC.wasReleased()) { showTempl(); M5.Lcd.setTextColor(BLUE); M5.Lcd.setCursor(0, 60); M5.Lcd.println("Device ID&PAC: "); M5.Lcd.setCursor(0, 78); Serial2.println("AT$I=10"); Serial2.println("AT$I=11"); } // 2秒毎に温湿度センサの値を読んで表示する else if (200 <= ++loopcount) { loopcount = 0; temp.f = dht.readTemperature(); humid.f = dht.readHumidity(); showTempl(); M5.Lcd.setTextColor(YELLOW); M5.Lcd.setCursor(10, 60); M5.Lcd.printf("Temperature: %3.1f C", temp.f); M5.Lcd.setCursor(10, 78); M5.Lcd.printf("Humidity : %3.1f", humid.f); M5.Lcd.setCursor(228, 78); M5.Lcd.print("%"); } // delayを大きくするとボタンイベントが取れないので10msでループさせる delay(10); } // 表示画面のテンプレート(タイトル、ボタン名など)を表示する。 void showTempl() { M5.Lcd.clear(BLACK); M5.Lcd.setTextColor(WHITE); M5.Lcd.setTextSize(2); M5.Lcd.setCursor(10, 10); M5.Lcd.println("Send Thermo Sensor data"); M5.Lcd.setCursor(10, 28); M5.Lcd.println("to Sigfox Backend Cloud."); M5.Lcd.setCursor(20, 220); M5.Lcd.print("SEND DATA"); M5.Lcd.setCursor(238, 220); M5.Lcd.print("ID/PAC"); } |
本当に運用するなら一定時間ごと(例えば30分ごと)にデータ送信するようにしますが、今はテスト目的なので左ボタンを押したらデータ送信するようにしました。右ボタンでDevice IDとPACを表示する機能も付けました。
Sigfoxに送信する温度と湿度の値はそれぞれfloat型の4バイトのデータです。そのデータを16進数に変換して送信しています。合計8バイトのデータサイズになっています。Sigfoxで送信できるのは1回につき12バイトまでなので、今回は問題ありませんが、他にも情報を送りたい場合はデータサイズが不足することも考えられます。その様な場合は、例えば温度を10倍して0.1度単位の整数データとして送れば2バイトでも送信可能です。湿度は1%精度で良ければ1バイトで済みます。そのようにしてデータ構造を設計してください。
送信されたデータを確認する
Sigfoxクラウドの管理画面でM5Stackから送信データを確認します。管理画面は下のURLから、デバイス登録の際の Email と Password でログインします。
“DEVICE” のタグを選択すると登録済のデバイスが一覧表示されるので、”id” と表示された番号をクリックします。
左側の “MESSAGES” を表示すると通信履歴が表示されます。今回のスケッチはAボタンを押すと16進で16桁のデータが送信されています。”Location” のボタンを押すとデバイスのおおまかな位置情報が取得されていることがわかります。
Callbackを設定する
Sigfoxクラウドに届いたメッセージに応じて、メールを発信したりWEBアプリに情報を送信したりすることができます。Sigfoxではこの機能をCallbackと呼んでいます。Sigfoxの管理画面には複数のデバイスを登録でき、”DEVICE” の画面で一覧表示できますが、デバイスをグループ化したものが DEVICE TYPE です。管理画面の “DEVICE TYPE” タブで表示されます。Callbackは DEVICE TYPEに対して設定します。
管理画面の “DEVICE TYPE” タブの中で、Callbackを設定するDEVICE TYPEの名前をクリックしてください。
左側のメニューからCALLBACKSを選び、右端の [New] ボタンを押します。
AWSやMicrosoft Azureに対応した機能がありますが、ここではCustom callbackを選択します。
試しに、Sigfoxクラウドに届いたデータをメールで転送するCallbackを作成してみます。TypeはDATA/UPLINK、ChannelはEMAILを選択し、Recipientにメールアドレスを記入します。SubjectとMessageは送信するメールの内容ですが、データを {変数名} という形で含めることができます。
ここで、”Custom payload config” の欄に記述した設定内容について説明が必要です。Sigfoxでは1回あたりの送信のデータサイズは12バイトまでと決まってます。今回のサンプルではM5Stackから送信するデータは温度と湿度それぞれ4バイト、合計8バイトのデータが次のような構造になっています。
温度データ | 湿度データ |
float型(4バイト) | float型(4バイト) |
このデータ構造をSigfoxに認識させるために “Custom payload config” の欄に次のように記述します。
1 |
temp::float:32 humid::float:32 |
これは、”temp” という名前で4バイト(32ビット)、”humid” という名前で4バイト(32ビット)のデータがフォーマットされていることを示しています。ここで定義した名前を使って、その内容を後で参照することができます。メール本文の内容として “Message” の欄に次のように記述しましたが、”{customData#temp}” と “{customData#humid}” で温度と湿度の値を参照しています。
1 2 3 |
Time: {time} Temperature: {customData#temp} Humidity : {customData#humid} |
[Ok]ボタンを押すとCallbackが登録されます。作成したCallbackのリストが表示され、左端のEnableで有効/無効を設定できます。EditボタンでCallbackの内容を編集できます。
以上でCallbackの設定ができました。M5Stackからデータを送信すると登録したメールアドレスに下のように通知が届きます。
以上、Callbackについて説明した内容は下記の記事を参考にしました。詳細はそちらを参照してください。
Sigfox Callback – Custom Payload Config機能
データ表示をカスタマイズする
少し前の手順で、M5Stackからのデータを表示しました。”DEVICE” のタグを選択、デバイスが一覧から “id” を選択し、”MESSAGES” を表示した状態です。
ここではデータが16進数で表示されています。Callbackの設定をするときにデータ構造に応じた処理が可能であることを学びましたが、”MESSAGES” の画面でも同様にカスタマイズができます。管理画面の “DEVICE TYPE” タブの中で対象の “Name” をクリックして、右上に表示されている “Edit” のボタンをクリックします。下の方に “Payload display” という設定項目があって、”Regular (raw payload)” になっていますが、これを “Custom grammer” に変更します。”Custom configuration” という欄が現れるので、ここに “Custom payload config” と同じように記述します。
1 |
temp::float:32 humid::float:32 |
[Ok]で設定を完了して、もう一度 “DEVICE” のタグ、デバイスが一覧から “id” 選択、”MESSAGES” を表示してみましょう。次のようにちゃんと温度・湿度が表示されているはずです。
WEBアプリサーバーを準備する
Sigfoxクラウド(下の図のSigfox Backend Cloud)まで温度データが届いていますので、次は温度データを受け取るWEBアプリサーバーを実装します。下の図のいちばん右側の部分です。データをグラフ表示してくれるAmbientや、他のサービスに中継してくれるIFTTTのようなサービスを使っても構いませんが、ここではFlaskで作ったWEBアプリに送信します。Ambientの例は後で示します。
WEBアプリは センサのデータをグラフ表示する で作ったものとほとんど同じです。WEB閲覧したときに1秒毎にリロードする動作が邪魔なので、 templates/index.html に含まれる <meta http-equiv=”refresh” content=”1; URL=”> の行を削除しました。ソースコードはGitHubにあります ので見てください。
次に、作ったFlaskアプリをHerokuにデプロイしました。デプロイする手順は 別の記事 を参照してください。Heroku上のアプリ画面は次のURLですのでアクセスしてください。
1 |
https://sigfox-sensor.herokuapp.com/ |
このアプリに手動でデータを送り込んでみましょう。そのためのスクリプトは先程のGitHubのリポジトリにもありますが、このようなものです。
senddata.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#! /bin/bash URL="https://sigfox-sensor.herokuapp.com/post" #URL="http://localhost:5000/post" curl "$URL?temp=20.0" read -p "Hit Enter key." curl "$URL?temp=20.2" read -p "Hit Enter key." curl "$URL?temp=20.3" read -p "Hit Enter key." curl "$URL?temp=20.6" read -p "Hit Enter key." curl "$URL?temp=20.7" |
WindowsならWSL、Macならターミナルから上記のスクリプトを実行してください。実行権限が必要なのであらかじめchmodコマンドを実行しておきます。
1 2 |
$ chmod +x senddata.sh $ ./senddata.sh |
Enterキーを押すたびにデータがひとつづつ送られて、ブラウザ上にこのように表示されるはずです。
CallbackでWEBアプリにデータ送信する
新しいCallbackを作って、データをWEBアプリに送信してみます。メール送信のCallbackを作ったときと同じようにCustom callbackを作成します。設定画面は下のようにChannelは “URL” に設定します。
WEBアプリはGETメソッドを使って受信するようになっているので、”Url pattern” はそれにあわせて記述します。”Use HTTP Method” は “GET” に設定します。
1 |
https://sigfox-sensor.herokuapp.com/post?temp={customData#temp}&humid={customData#humid} |
設定が終わっったら [Ok] ボタンを押して、メール送信のCallbackは不要なら無効に設定しておいてください。
M5Stackの左ボタンを押してデータ送信し、HerokuのURLにアクセスするとデータが反映されています。
Herokuのログを見るとSigfoxからアクセスが有ったことが確認できます。
Ambientでグラフ表示する
独自のWEBアプリサーバーを立ててデータを受信する方法を説明してきましたが、既存のWEBサービスを使うこともできます。Ambientを使ってデータをグラフ表示する方法を以下に示します。
Ambient https://ambidata.io/ でアカウントを作成します。無料で可能です。
Ambient上でチャネルを作成します。チャネルの [設定] > [設定変更] でデータの名称などを設定します。
チャネルのボード画面でチャートを作成します。設定画面は例えば下のようにします。”d1″ を温度、”d2″ を湿度に定義しています。
チャネル一覧の画面で “チャネルID” と “ライトキー” の値を控えておきます。
Sigfoxクラウドからデータを送信するにはCallback機能を使います。設定画面は下のようにします。Url pattern の一部にAmbientのチャネルIDを指定します。POSTメソッドで送るJSONデータの中にAmbientのライトキーを指定してください。
M5stackからデータを送信して、暫くしてからAmbient側でチャネルのチャートを表示すると反映されているはずです。
まとめ
温湿度センサ → M5Stack → Sigfoxクラウド → WEBアプリ(Heroku) というデータの流れを構築することができました。
- Sigfoxは24時間連続運転で小さなデータ量を通信するには良いサービスですが、1日あたりの通信回数・データサイズ等に支障がある場合は他のLPWAサービスを検討してください。
- WEBアプリはHerokuにデプロイしましたが、Herokuの無料プランは一定時間アクセスがないとプロセスがスリープ状態になる等の制限事項があります。また、一定期間ごとにプロセスが初期化されますのでデータがリセットされてしまいます。実際に運用する際にはHeroku以外のサービスを利用するか、HerokuのオプションのPostgresデータベースを利用してデータを永続化する等の対策が必要です。
- 今回実装した内容ではスマホからもブラウザでアプリにアクセスできますが、AndroidやiPhoneのアプリを作成すればよりスマートなLook&Feelを実現できるかもしれません。その場合にはWEBアプリ側にスマホ用のAPIの実装が必要になるかもしれません。
コメント