こんにちは。 す〜 ( @ksksue ) です。 前回の記事「さくらIoT Platformをさわって遊んでみる」の続きで Akerun Advent Calendar 12 日目の記事です。
ざっくりこんな感じで書き進めています。
- さくらIoTさわってみる
- nRF52とつなげてみる ← イマココ
- Akerun Pro 遠隔で開けてみる(次回)
今回はNordic nRF52 と繋いでゴニョゴニョしようと思います。
早速ですが、さくらIoTモジュールとI2Cで繋ぐためのnRF52ライブラリを作ったので github で公開しておきます。 ※ 公開しているコードは個人の趣味の制作物です
GitHub - ksksue/sakura_iot_beta_nrf52_i2c: さくらのIoT Platform βとnRF52をI2Cで繋げるためのコード
使い方は後で書くとして、まずはnRF52についてちょっと紹介しておきます。
Nordic nRF52 BLE の紹介
最近やたらと各ベンダがBLEチップを出しまくってますが、その中でもnRF52はかなりいいツールです。
- オープンソース文化の色が濃い
- 地雷を踏んでも公式コミュニティサイトDevZone(stack overflow風QAサイト)でなんとかなる
- 最新技術を取り込むのが早い
nRF52 : オープンソース文化の色が濃い
他ベンダの開発環境は組込み色が濃い中、Nordicはわりとオープンソースの文化を引き継いているため、 サンプルコード、オープンだと助かるツールのコードが github にアップされています。 Nordic Semiconductor · GitHub
また、マイコンのC言語のコードを眺めてみるとトリッキーな書き方は避けリーダブルなコードを目指していることがわかります。 C言語でマイコンドライバを書き進めるときの素直なコードを書くときの参考になります。
ほぼオープンソースなので、実際にはAkerun ProではOTAでファームをBLE通信するときの独自暗号化通信対応などができるところで助かりました。
Akerun ProではWebの暗号化通信がそのままデバイスまで降りてきているという、マイコンレベルではかなりリッチな暗号化を施しているのですが OTAも同じ暗号化技術を使って通信内容の暗号化をすることができました。
それでも高速に処理できるほどのCPUパワーがあるのもnRF52の魅力ポイントです。
nRF52 : 地雷を踏んでも公式コミュニティサイトDevZoneでなんとかなる
Stack overflowライクなコミュニティサイトがあります。 Googleからも検索にひっかかるので、エラーコメントを検索するだけで上位にひっかかってきてくれます。
nRF52 : 最新技術を取り込むのが早い
最新技術を取り込むのが早いという点もイケてるポイントです。 2016/12/7にBluetooth 5 が公式採択されたばかりですが、その日にNordicからBluetooth 5の開発ボードが発売開始となりました。
ちなみにBluetooth 5 はBluetooth 4.2に比べて、通信範囲 4倍、通信速度 2倍、メッシュネットワーク対応という これまでなんだったの感があるくらい飛躍を遂げている仕様なのでPhotosynth社内でも注目しています。
今のところBluetooth 5対応の開発ボードは日本未Shipping状態(2016/12/12現在)なのですが Nordicの開発ボードを手に入れて実際の技術を体験できることを楽しみにしています。 ※ 要電波暗室
【本題】さくらIoT モジュールとNordic nRF52 BLE を繋げる
さてnRF52についての紹介はこのあたりにして、本題です。実際にnRF52とつなげて通信してみます。
nRF52-DK(要電波暗室)などを使って、図のようにつなげます。I2C電圧レベル変換ICを噛ましてるだけです。
nRF52 BLE ライブラリを使う
さくらIoTモジュール駆動用にnRF52ライブラリとして26個の関数を作りました。 ファイルダウンロード系が今のところサポートされていないようなのでそれ以外の関数です。 ソースコードはgithubにアップしてあります。
GitHub - ksksue/sakura_iot_beta_nrf52_i2c: さくらのIoT Platform βとnRF52をI2Cで繋げるためのコード
※ 何度も言いますが個人趣味の範囲でやってることなのであしからず
void drv_sakura_iot_init(void); //********************************************************** // general commands //********************************************************** uint8_t drv_sakura_iot_get_connection_status(void); uint8_t drv_sakura_iot_get_signal_quality(void); uint8_t drv_sakura_iot_get_date_time(sakura_iot_date_time_t *date_time); uint8_t drv_sakura_iot_echo_back_test(uint8_t length, uint8_t *indata, uint8_t *outdata); //********************************************************** // IO commands //********************************************************** uint8_t drv_sakura_iot_read_adc(uint8_t ch, uint16_t *volt); //********************************************************** // data tx commands //********************************************************** uint8_t drv_sakura_iot_tx_enqueue(txrxdata_t *data); uint8_t drv_sakura_iot_tx_immediately(txrxdata_t *data); uint8_t drv_sakura_iot_tx_available_queue_length(void); uint8_t drv_sakura_iot_tx_queued_length(void); uint8_t drv_sakura_iot_tx_queue_flush(void); uint8_t drv_sakura_iot_tx_queue_send(void); uint8_t drv_sakura_iot_get_tx_queue_status(void); uint8_t drv_sakura_iot_get_tx_immediately_status(void); //********************************************************** // data rx commands //********************************************************** uint8_t drv_sakura_iot_rx_dequeue(txrxdata_t *data); uint8_t drv_sakura_iot_rx_queue_peek(txrxdata_t *data); uint8_t drv_sakura_iot_get_rx_available_queue_length(void); uint8_t drv_sakura_iot_get_rx_queued_length(void); uint8_t drv_sakura_iot_rx_queue_flush(void); //********************************************************** // etc command //********************************************************** uint8_t drv_sakura_iot_get_product_id(uint8_t *pid); uint8_t drv_sakura_iot_get_unique_id(uint8_t *uid); uint8_t drv_sakura_iot_get_firmware_version(uint8_t *version); uint8_t drv_sakura_iot_unlock(void); uint8_t drv_sakura_iot_firmware_update(void); uint8_t drv_sakura_iot_get_firmware_update_status(void); uint8_t drv_sakura_iot_software_reset(void);
ざっくりと initして叩けばOKです。
drv_sakura_iot_init(); uint8_t st = drv_sakura_iot_get_connection_status(); if(st == DRV_SAKURA_IOT_CONNECTION_STATUS_CONNECTED) { DPRINTF("connected!"); }
という感じです。 コネクションを確認できたらさくらIoTモジュールのTx FIFOにキューしてsendすればデータを送れます。
txrxdata_t txdata; txdata.ch = 0; txdata.type = 'i'; txdata.data.ui = 0x12345678; drv_sakura_iot_tx_enqueue(&txdata); drv_sakura_iot_tx_queue_send();
カンタンですね。
データの受信はWAKE_OUTで割込み信号が取れるようですが、 ここではポーリングで対応。GPIO割込みコードを書けばWAKE_OUT対応はすぐできます。
uint8_t rx_queue_num; txrxdata_t rxdata; while(1) { rx_queue_num = drv_sakura_iot_get_rx_queued_length(); if(rx_queue_num != 0) { drv_sakura_iot_rx_dequeue(&rxdata); DPRINTF("rxdata ch:%d type:%02x data:%d\n", rxdata.ch, rxdata.type, rxdata.data.ui); } nrf_delay_ms(10); }
これでデータの送受信ができるようになります。
ちなみにこのライブラリでは書き方を簡易化するためI2Cは同期通信に書き直しています。(nRF52のI2Cドライバ内では非同期)
さくらIoT Platformのクラウド側の準備
さて、そのデータの送受信先のクラウドの準備をします。
デバイスの登録などは公式ドキュメントを参考にしてください。
https://iot.sakura.ad.jp/developer/pdf/iot_platform_manual_beta.pdf
PC → さくらクラウド → さくらIoTデバイス → nRF52
PC→さくらIoTデバイス、のデータ通信をするために incoming webhookを作っておきます。
その状態で、PCからincoming webhookを経由してさくらIoTモジュールへデータを送信するpythonコードを以下に書いておきます。
#!/usr/bin/env python import hmac import hashlib import requests import json secret = "" data = {"module": "xxxxxxxx","type": "channels","payload": {"channels": [{"channel": 0,"type": "i","value": 123456789}]}} payload = json.dumps(data) x_sakura_signature = hmac.new(secret.encode("utf-8"), payload.encode("utf-8"), hashlib.sha1).hexdigest() print(x_sakura_signature) headers = {'X-Sakura-Signature' : x_sakura_signature} r = requests.post('https://api.sakura.io/incoming/v1/moemoe', data=payload, headers=headers) print(r.text)
※ moduleのxxxxxxxx部分にはモジュールのID、incoming/v1/moemoe の部分にはTokenを入れます。secretは未動作確認。
参考: SakuraIoTAlphaDocs/services.md at master · sakura-internet/SakuraIoTAlphaDocs · GitHub
このpythonコードを叩くとPCから
channel : 0 type : 'i' value : 123456789
の情報をクラウドへ送ることが出来ます。
さくらクラウドはさくらIoTモジュールへこの情報を送信し、nRF52でそのデータを取り込み、 nRF52のデバッグコンソールに以下の文字が流れます。
rxdata ch:0 type:i data:123456789
nRF52 → さくらIoTデバイス → さくらクラウド
デバイスからデータがクラウドへ流れているかを確認するのにwebsocketがカンタンなので さくらクラウドサーバ側でwebsocketのプロジェクトを作っておきます。
上記のnRF52のコードを叩くと、さくらクラウドの画面にデータがきていることが確認できます。
drv_sakura_iot_tx_enqueue(&txdata); drv_sakura_iot_tx_queue_send();
まとめ
さて、駆け足でしたがnRF52とさくらIoTモジュールをつなげてデータ送受信するところまできました。
マイコンモジュールからクラウドへダイレクトにデータ通信できるというのはおもしろいですね。 ボクは組込み屋ですが、クラウド側をもっといじりたいと思いました。
次回はAkerun Proに繋いでパカーっと鍵を開けるところまで行ってみたいと思います。
参考サイト
Nordic Semiconductor http://www.nordicsemi.com/
Bluetooth 5 https://www.bluetooth.com/specifications/bluetooth-core-specification/bluetooth5
さくらのIoT Platform | 開発者向け https://iot.sakura.ad.jp/developer/
告知
Akerunをつくっている株式会社フォトシンスではRailsエンジニアを募集しています! www.wantedly.com
Akerun Developersサイトもやってます。Akerun APIについては、こちらをご覧ください。 photosynth-inc.github.io