M2M

2015年10月08日

ESP8266 モジュール + Blynk でさらりと Wake On Wan

はてなブックマークに登録

Android / iOS 端末から所定の IoT デバイスの遠隔制御や監視を可能とする Kickstarter 発の Blynk が人気を集めています。2015年10月現在 Blynk はまだ開発の途上にあり、今の時点では Backer(出資者)でなくとも実装ずみのすべての機能を無償で利用することができます(※)。シンプルで取りまわしのしやすいこのサービスを使い、ちょっとした実用性のある道具として遠隔の PC をスマホで Wake On Wan するものを作ってみました。なかなか便利なので一式を公開します。

  • (※)公式サイトの「FAQ」より
    + I backed Blynk on Kickstarter. Where are my widgets and
      why the app is free?
    
      - App is free becasuse otherwise you would have to pay to
        download it. This is how AppStore and Google Play works.
      - Current Blynk release has a limited amount of widgets.
        We decided to make them free for everyone until we
        implement store. After that,every widget will be paid.
        However every backer will get them for free (according
        to their pledge).
    
Blynk は ESP8266 Wi-Fi モジュールに対応しており、以下の記事では技適マークつきの「ESP-WROOM-02」を使用しています。このシリーズのモジュールは自立したマイコンとして動作可能であるため IoT デバイスの主要素としてもっとも手軽な選択肢のひとつと言えるでしょう。

準備

まず Blynk の利用を構成するみっつの要素を整理しておきます。

  • Blynk アプリ
    Google Play / AppStore で公開中の専用アプリを使ってユーザが構成した制御用のアプリ
  • IoT デバイス
    専用の Blynk ライブラリを使ってユーザが作成したプログラムを導入ずみの制御対象の装置
  • Blynk サーバ
    Blynk アプリと IoT デバイスの連係を仲介するクラウドサービス(※オープンソースであり自前での構築も可能)

Android / iOS 端末にはそれぞれの公式ストア上で配布されている専用のアプリ「Blynk」をインストールします。利用者はこのアプリを使って独自の Blynk アプリを構成することができます。
Blynk アプリに対向する IoT デバイスのためのプログラム開発には Arduino IDE を使用します。あらかじめ IDE に ESP8266 用ライブラリモジュールを導入しておき、そこへ Blynk の提供するライブラリ群をインストールします。
Blynk の公式ドキュメントには Blynk を利用する上で必要となるこういった情報・手順がわかりやすく記述されています。また、ネットを検索すれば多くの有用な記事を参照することができます。

試作の題材について

手元のニーズに基き、Blynk を使った遠隔制御の身近な応用例として次の内容を想定しました。IoT デバイスは対象の PC と同じ LAN 環境へ設置します。

  1. 所定の PC を Wake On Wan する
  2. 所定の PC へ ping を打つ
  3. 所定の AC 機器への給電を ON / OFF する
  4. 制御対象の IoT デバイスをリセットする

外出中に自宅の PC を利用したくなる場合があります。PC をずっと起ち上げたままにしておくのは好ましくないので、これまでは遊んでいる Android 端末を自宅で待機させておき GCM 経由で所定の PC を Wake On Lan するという方法をとっていました。それはそれで問題なく機能しているのですが、必要な手順を踏むのがだんだん面倒になってきたことに加え、その場で手早く PC の起床状況を確認できないことに不便を感じていました。確認方法は所定の IP アドレスに対する ping テストで十分でしょう。

上記 3.は拡張用です。手元では留守の夜の防犯用に自宅の部屋の電灯を任意のタイミングで点灯/消灯するために使っています。これまでは上の PC に接続した USB 赤外線リモコンで操作を行っていましたが、それも面倒なので別の手段がほしいと思っていました。

実装方法について

Wake On Lan マジックパケットの送出と所定の PC への ping 打ちは Blynk の「Virtual Pin」機能を使って IoT デバイス側と連携すれば簡単に実現できると考えました。Blynk アプリ上に配置したボタンの設定において「OUTPUT」に物理ピンではなく適当な仮想ピンの番号を割り当てて、受け側の IoT デバイス側のコードに "BLYNK_WRITE(仮想ピン番号)" ハンドラを定義してそこに必要な処理を記述すればよいはずです。

  • Send data from app to hardware - Blynk 公式ドキュメント - blynkkk.github.io
    Send data from app to hardware
    
    You can send any data from Widgets in the app to your
    hardware.
    
    All Controller Widgets can send data to Virtual Pins on
    your hardware. 
    For instance, code below shows how to get values from
    the Button Widget in the App
    
    BLYNK_WRITE(V1) //Button Widget is writing to pin V1
    {
      int pinData = param.asInt(); 
    }
    
    When you press Button, Blynk App sends 1 On second
    click - it sends 0
    
    This is how Button Widget is set up:
  • Wake On Lan マジックパケットの仕様に関する記事
  • Espressif 社公式フォーラムの以下の記事の末尾に ESP8266 で ping を実行するサンプルコードあり
ping 結果をアプリへ通知するには、アプリ側に設置したデータ INPUT 用のウィジェットに所定の仮想ピン番号を設定しておき、その番号に対し IoT デバイス側のコードで "Blynk.virtualWrite(仮想ピン番号, データ)" API を使ってデータを送ってやればよさそうです。

  • Virtual Pins - Blynk 公式ドキュメント - blynkkk.github.io
    Virtual Pins
    
    Virtual Pins are designed to send any data from your
    microcontroller to the Blynk App and back. Think about
    Virtual Pins as channels for sending any data. Make sure
    you differentiate Virtual Pins from physical pins on your
    hardware. Virtual Pins have no physical representation.
    
    Virtual Pins can be used to interface with libraries
    (Servo, LCD and others) and implement custom functionality. 
    The device may send data to the Widget to the Virtual Pin
    like this:
    
    Blynk.virtualWrite(pin, "abc");
    Blynk.virtualWrite(pin, 123);
    Blynk.virtualWrite(pin, 12.34);
    

AC 機器への給電の ON / OFF の制御には ESP8266 モジュールからの 3.3V 出力信号でリレースイッチを操作すればよいでしょう。入力側と出力側の絶縁性の高いソリッドステートリレー(SSR) は動作時にカチリと音のする有接点リレーに比べ値段が高めですが秋月電子さんが電子工作向きの手頃なキットを販売しています。

※余談ながら、個人的にはこのように高電圧を扱うものは本当はあまり自作したくないです。その方面に素養がなくても部品を揃えれば作るのは簡単ですが、「手作りの楽しさ」などよりも安全性がもっとも重要ですから、手頃な価格で堅牢な完成品を入手できるならそれを使いたいというのが正直なところです。残念ながら今のところそういう商品は見当たらないようですが(需要はあると思うのですが・・)、上のキットを使ってリレーつき電源ケーブルを作る方法が下記の書籍にわかりやすく記載されています。

動作の様子

ひと通り形になったものが動作している様子を以下の動画に収めています。(1分56秒 環境音あり)

内容:

  • IoT デバイス稼働中は死活確認用の LED が 2秒間隔で点滅、そのタイミングでアプリの TICK フィールド(デバイス稼働秒数)が更新される
  • アプリの BOOT PC ボタン押下で IoT デバイスが所定の PC を Wake On Lan する
  • アプリの PING ボタン押下で IoT デバイスが所定の PC へ ping を投げアプリの OK / NG フィールドへ結果をカウント
  • アプリの AC DEVICE ボタン押下で IoT デバイスへ接続した AC 機器への給電を ON / OFF
  • アプリの RESTART ボタンを長押し(3秒以上)してリリースすると IoT デバイスは再始動する

リソース一式

今回の Blynk アプリおよび IoT デバイスを構成する要素は以下のとおりです。

※各画像はクリックで実寸表示

Blynk アプリ側

Android / iPhone での当該 Blynk アプリの画面表示

プロジェクトと各ウィジェットの設定

IoT デバイス側

装置全体の様子
※ESP-WROOM-02 モジュールは Cerevo 社製のブレイクアウト基板「CDP-ESP8266」とともに使用
※稼働状況確認用に IO4 に赤色 LED を、AC 機器制御用に IO12 にリレーつきケーブルを装着しているが不要ならどちらも省略可

リレーつき電源ケーブル

ソースコード
SimpleTimer ライブラリのインストールが必要です)

ESP8266_WakeOnWan.ino - github.com/mkttanabe

留意すべき事項など

Blynk は便利で有用ですが現在進行形で開発中であるため利用時に若干注意しなければならない点もあります。今回手元で気づいた話題をメモしておきます。

Blynk ライブラリ旧バージョンでの不具合について(重要)

2015-08-06 にリリースされた v0.3.0 までのBlynk ライブラリには ESP8266 モジュールのハンドリングに大きな不具合があります。同モジュール − Blynk サーバ間の持続接続に不意に切断が発生した場合に無限ループに陥りデバイスをリセットしない限り再接続不能となる問題です。この不具合は 2015-09-24 にリリースされた v0.3.1 では修正されており、切断が発生した場合に接続を自動復旧する機構が正常に機能するようになっています。この修正により連続稼働が安定するようになりました。Blynk で ESP8266 を使う場合は必ずこの v0.3.1 以降のライブラリを使うべきです。公式フォーラム上の以下の記事に関連する応酬があります。

Android - iOS 端末間の Blynk アプリの互換性について

Blynk は Android と iOS に対応していますが、両方のプラットフォームで等しく動作する Blynk アプリを構成するためには以下の点への注意が必要です。

  • 2015年10月8日時点の Android 版 Blynk の最新バージョンは "1.0RC7 fix"、iOS 版 Blynk の最新バージョンは "1.3" です。バージョン番号は iOS 版のほうが上ですが、Android 版で利用可能なウィジェットうち iOS 版ではまだ実装されていないものがいくつかあります。下図左は Android 版 "1.0RC7 fix、右は iOS 版 "1.3" でのウィジェット一覧です。

    iOS 版未実装のウィジェットを Android 版で配置して保存したアプリを iOS 版で開くとその部分が空白となります。それだけではなく、そのアプリを iOS 版で保存すると当該ウィジェットは失われます。要注意です。


  • Android 版では LED ウィジェットが正常に機能しません
以上の事情により、現時点では、両プラットフォーム間での互換性の確保が必要なアプリにおいては iOS 版で利用できるウィジェットのみを使用し、また、LED ウィジェットは使わないようにする必要があります。今後の改善が期待されます。

最後に

Prepare to Blynk! - www.kickstarter.com に掲載されているイラスト

がんばれ Blynk!


(tanabe)
klab_gijutsu2 at 05:49|この記事のURLComments(0)
2015年08月27日

ESP8266 モジュールの AT コマンドに SSL クライアント機能を追加する

はてなブックマークに登録

中国 Espressif Systems 社製 ESP8266EX 搭載の「ESP-WROOM-02」は興味ぶかいモジュールです。 今年(2015年)上半期に技適を取得し人気を集めているこの製品は安価であるにも関わらず自立したマイコンとして扱える点が素晴らしく、また、出荷時のファームウェアに組み込まれている AT コマンドセットを利用すればホスト側に負荷をかけず簡単に丸ごと通信処理を代行してくれる手軽さにも好感が持てます。

ただ、この AT コマンドセットで HTTPS リクエストを処理する方法が見当たらないことを不思議に思っていました。あらためてドキュメントを確認するとどうやら AT コマンドで SSL 通信を扱うことはできないようです。プログラマブルであることがこの製品の魅力のひとつであるとは言え 出荷時の状態で SSL を利用できないのはそのこと自体が残念に思われます。AT コマンドのインターフェイスそのものは何かと便利なのでこれを拡張する形で SSL への対応を試みました。

最終的にはサーバ証明書の検証も含め期待通りに動作しましたが、その過程で意外な曲折もあり、手元で経験したことを備忘をかねてほぼ順番どおりに記録しておくことにします。興味のある方は追ってみて下さい。

AT コマンド拡張について

メーカーは次のページで ESP8266 用の SDK を公開しています。

2015-08-21 時点の最新版は以下の通りです。

SDK アーカイブを覗いてみると examples/at/ ディレクトリ下に AT コマンドセットを拡張するためのサンプルコードが収録されており「AT+CIUPDATE」コマンドは他のコマンド群とは別にここで定義されていることが見てとれます。

examples/at/user/user_main.c

コードの末尾付近の at_custom_cmd[] テーブルには「AT+CIUPDATE」に加え「AT+TEST」という拡張コマンドが記述されています。拡張コマンドの定義の方法は次の記事に説明があります。

In the example of \esp_iot_sdk\examples\at\user\user_main.c, 
ways are delivered on how to implement a self-defined AT Command,
 AT+TEST”.
The structure, at_funcationType, is used to define four types of
a command, e.g., “AT+TEST”. 

"at_testCmd" is a testing command and it’s formatted as AT+TEST=?.
In the example of AT, the registered callback is “at_testCmdTest”; 
the testing demand could be designed as the value range of the
return parameter. If registered as NULL, there will be no testing
command.

"at_queryCmd" is a query command and it’s formatted as AT+TEST?.
In the example of AT, the registered callback is “at_queryCmdTest” ; 
the query command could be designed as returning the current value. 
If registered as NULL, there will be no query command.

"at_setupCmd" is a setup command and it’s formatted as
AT+TEST=parameter1,parameter2,........ In the example of AT, 
the registered callback is "at_setupCmdTest"; 
the setup command could be designed as the value of the parameter; 
if registered as NULL, there will be no setup command.

"at_exeCmd" is an execution command and it’s formatted as AT+TEST. 
In the example of AT, the registered callback is “at_exeCmdTest”; 
if registered as NULL, there will be no execution command.
一連の書式は他のコマンドでも見かけるものです。一読したところでは既存のコマンドセットにオリジナルの AT コマンドを追加することはあまり難しくないようです。

SDK に同梱のビルドずみファームを書き込んでみる

SDK の bin/ ディレクトリにはメーカー側がビルドしたファームウェアバイナリ群が格納されています。
ESP-WROOM-02 出荷時の標準ファーム(AT コマンドセット)は以下のバイナリから構成されます。

  • bin/boot_v1.2.bin ---- ブートローダ
  • bin/at/user1.1024.new.2.bin ---- AT コマンドプログラム本体
  • bin/blank.bin ---- 領域初期化用 中身は 0xFF * 4096バイト
  • bin/esp_init_data_default.bin --- "Stores default RF parameter values"

自作のファームをビルドして書き込む前に、まずこれらを練習台として内蔵フラッシュメモリに書き込んでみることにしました。 正しく書き込めるようになっておけばいざと言うときの切り戻しも楽でしょう。

「bin/at/readme.txt」冒頭に次の記述があります。

download:
boot_v1.2+.bin      	0x00000
user1.1024.new.2.bin  	0x01000
blank.bin           	0x7e000 & 0xfe000

※「user1.1024.new.2.bin」の「1024」は 1024KB(8Mbit)容量のフラッシュメモリ使用を想定してビルドされたバイナリであることを意味する。ESP-WROOM-02 は 32Mbit のフラッシュメモリを内蔵しているが、以下の記事においてはこのバイナリの仕様に準じ 8Mbit 空間範囲の使用を前提とする。

※「esp_init_data_default.bin」には RF(Radio Frequency)パラメータのデフォルト値が保持されている旨の説明が SDK の「ESP8266 IOT SDK User Manual」に記載されている。次の記事にも説明あり。

ファームウェアの書き込みは以下の「Flash Download Tool」を使い USB - シリアル変換器経由で行います。ツールは Windows 版と Python 版が用意されています。 書き込みはモジュールの IO0 ピンを Lo にセットして「UART Download Mode」へ移行し次の要領で。
(図は Windows 版)
    ※1024KB フラッシュ使用時のメモリマップ
    
         - SDK の「Espressif IOT SDK User Manual」より
    
    Note 
    
    • System param (system parameter area) is the last 16KB offlash. 
    
    • User param is the user parameter area used by Espressif demo code
      ( IOT_Demo or AT ). If users develop their own application, 
      user data can be saved in any available flash area. 
    
    • User Data area ( green area in pictures below ) means the flash
      area that may be available, if program area doesn’t reach the
      maximum size, remaining area can be used to save user data. 
    
動作確認
AATTEE00


OK
AT+GMR
AT version:0.40.0.0(Aug  8 2015 14:45:58)
SDK version:1.3.0
compile time:Aug  8 2015 17:19:38
OK
AT+CWMODE=1

OK
AT+CWLAP
+CWLAP:(1,"GPMAP",-93,"10:6f:3f:XX:XX:XX",1,-47)
+CWLAP:(0,"000D0BF6C164_G",-91,"00:16:01:XX:XX:XX",5,-32)
+CWLAP:(3,"hogehogeSSID",-72,"00:22:cf:XX:XX:XX",10,-91)
+CWLAP:(2,"STWEBKAIGI",-88,"4c:e6:76:XX:XX:XX",10,-27)
+CWLAP:(4,"elecom2g-DE8564",-90,"00:90:fe:XX:XX:XX",10,-26)
+CWLAP:(3,"e-timer-DE8564",-90,"02:90:fe:XX:XX:XX",10,-26)
+CWLAP:(3,"auhome_acyCYh",-92,"8c:4c:dc:XX:XX:XX",1,-31)

OK

開発環境の導入

ESP8266 モジュールのファームウェア開発には現在 Arduino 向けの IDE・言語を用いることも可能ですが SDK に含まれるコードはいずれもネイティブの開発環境を前提としているため今回はそれを使います。

メーカーは必要な一式をインストールずみの開発環境(Linux)の VirtualBox 仮想マシンイメージを配布しており、導入手順・方法は以下の記事で説明されています。

ポイントなど
  • SDK の一式を配置した PC 上のディレクトリを "share" の名前で VirtualBox 仮想マシンの共有フォルダとして設定しておく
  • 仮想マシンのデスクトップ上の "LXTerminal" を起動するとアカウント esp8266 でターミナルが開く
  • アカウント esp8266 ホームディレクトリの ./mount.sh を実行すると PC 上の共有フォルダが ~/Share にマウントされる
  • アカウント esp8266 のパスワードは "espressif"

※仮想マシンのタイムゾーンは CST 北京時間に設定されているため変更が必要です

ファームウェアをビルドしてみる

SDK の examples/ 下には複数のサンプルプロジェクトが配置されており、利用するプロジェクトのファイル群をそこから app/ 下へ丸ごとコピーして使います。今回は前述のとおり examples/at/* を使用します。

仮想マシン側で app/ へ移動し gen_misc.sh スクリプトを実行するとバイナリがビルドされます。 以下のビルド開始時のオプション指定はメーカー側ビルドでの内容に準じています。

$ pwd
/home/esp8266/Share/esp_iot_sdk_v1.3.0_15_08_08_build/esp_iot_sdk_v1.3.0/app

$ make clean
make -C user clean;
make[1]: Entering directory `/mnt/Share/esp_iot_sdk_v1.3.0_15_08_08_build/esp_iot_sdk_v1.3.0/app/user'
rm -f -r .output/eagle/debug
make[1]: Leaving directory `/mnt/Share/esp_iot_sdk_v1.3.0_15_08_08_build/esp_iot_sdk_v1.3.0/app/user'
rm -f -r .output/eagle/debug

$./gen_misc.sh
gen_misc.sh version 20150511

Please follow below steps(1-5) to generate specific bin(s):
STEP 1: choose boot version(0=boot_v1.1, 1=boot_v1.2+, 2=none)
enter(0/1/2, default 2):
1
boot mode: new

STEP 2: choose bin generate(0=eagle.flash.bin+eagle.irom0text.bin, 1=user1.bin, 2=user2.bin)
enter (0/1/2, default 0):
1
generate bin: user1.bin

STEP 3: choose spi speed(0=20MHz, 1=26.7MHz, 2=40MHz, 3=80MHz)
enter (0/1/2/3, default 2):

spi speed: 40 MHz

STEP 4: choose spi mode(0=QIO, 1=QOUT, 2=DIO, 3=DOUT)
enter (0/1/2/3, default 0):

spi mode: QIO

STEP 5: choose spi size and map
    0= 512KB( 256KB+ 256KB)
    2=1024KB( 512KB+ 512KB)
    3=2048KB( 512KB+ 512KB)
    4=4096KB( 512KB+ 512KB)
    5=2048KB(1024KB+1024KB)
    6=4096KB(1024KB+1024KB)
enter (0/2/3/4/5/6, default 0):
2
spi size: 1024KB
spi ota map:  512KB + 512KB


start...

make[1]: Entering directory `/mnt/Share/esp_iot_sdk_v1.3.0_15_08_08_build/esp_iot_sdk_v1.3.0/app/user'
DEPEND: xtensa-lx106-elf-gcc -M -Os -g -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions
-nostdlib -mlongcalls -mtext-section-literals -ffunction-sections -fdata-

(中略)

!!!
Support boot_v1.2 and +
Generate user1.1024.new.2.bin successully in folder bin/upgrade.
boot.bin------------>0x00000
user1.1024.new.2.bin--->0x01000
!!!

以上の手順で bin/upgrade/ 下に生成される user1.1024.new.2.bin を前出の bin/at/user1.1024.new.2.bin の代わりにフラッシュメモリの 0x01000 番地を起点に書き込めば完了です。

なお、boot*.bin, blank.bin はユーザによるビルドの対象ではありません。これらは SDK に含まれているものをそのまま使います。

HTTPS クライアント処理はどのように書けばいいの?

SDK にはドキュメントとして「ESP8266 SSL User Manual」が同梱されています。しかし、現時点では ESP8266 モジュールでの SSL 利用に関する情報は少ないのが実状です。

ちなみに、IBM 所属の Neil Kolban 氏が 2015年8月1日に公開した「Kolban's book on the ESP8266」は技術情報が詳細に記述された貴重な資料ですが、同著においても SSL 処理については API の紹介のみに留まっています。

各国の利用者も手探りの途中といった印象で次のような応酬が随所で見受けられます。


By helpme -  Tue Jun 30, 2015 5:14 am

Can the ESP8266 support HTTPS websites? Does the Espressif SDK
support SSL function?
By Angelo Santagata -  Tue Jun 30, 2015 4:51 pm

Alas I no, but I happened to see this ESP8266 SSL Example on their website!
http://bbs.espressif.com/viewtopic.php?f=21&t=389

hopefully someone can port it to the SDK
というわけで、メーカー側は下記ページに HTTPS クライアント処理のサンプルコードを掲載しています。

Here is a demo code of ESP8266 as TCP SSL client. 
It is based on ESP8266 SDK without OS.

It just like ESP8266 to be normal TCP client except
change espconn_xxx to be espconn_secure_xxx

If your SSL packet is larger than 2048 bytes, please
try to call espconn_secure_set_size
to enlarge SSL buffer size (max:8192 )

このコードを下敷きに AT コマンドを拡張すればよいと考えました。

AT コマンド拡張では SSL 処理が正常動作しない?? (SDK v1.2.0)

さっそく自作の +GETTEST コマンドを書いてみました。
ちなみにこの実験の時点で使用していた SDK は 2015年8月初旬当時の最新版だった v1.2.0 です。

試作した +GETTEST コマンドは次の内容です。

AT+GETTEST="hostname" で当該ホストへ "GET /" リクエストを送る

AT+GETTEST  --- 引数がなければ www.example.com:80 へ HTTP リクエスト

AT+GETTEST="www.example.com",0 --- 2nd arg が 0 なら
                                   80番ポートへ HTTP リクエスト
AT+GETTEST="www.example.com",1 --- 2nd arg が 1 なら
                                   443番ポートへ HTTPS リクエスト

AT+GETTEST="www.example.com",1,0 --- 3rd arg が 0 ならサーバ証明書検証なしで
                                     443番ポートへ HTTPS リクエスト
AT+GETTEST="www.example.com",1,1 --- 3rd arg が 1 ならサーバ証明書検証ありで
                                     443番ポートへ HTTPS リクエスト
ソースコードを以下に示します。
(注:これらはその後の調査結果も反映したものです。最初の実験の段階ではずっとラフな内容でした) ところがこの AT+GETTEST コマンドは期待通りには動作しませんでした。HTTP リクエストは正しく処理されるものの HTTPS リクエストではエラーが発生するのです。
AATTEE00


OK
AT+GMR
AT version:0.30.0.0(Jul  3 2015 19:35:49)
SDK version:1.2.0
compile time:Aug 11 2015 14:09:10
OK


AT+GETTEST="www.example.com",1
mode : sta(18:fe:34:a4:0f:a0) + softAP(1a:fe:34:a4:0f:a0)
add if0
11
f 0, 221
scandone
add 0
aid 4

connected with hogehogeSSID, channel 10
WIFI CONNECTED
dhcp client start...
WIFI GOT IP
ip:10.10.0.19,mask:255.255.255.0,gw:10.10.0.1
got ip !!!
start connect to server
client handshake start. 
client handshake failed
reconnect callback, error code -28 !!! 
エラーコード -28 は SDK の include/espconn.h に定義されています
/* Definitions for error constants. */

#define ESPCONN_OK          0    /* No error, everything OK. */
#define ESPCONN_MEM        -1    /* Out of memory error.     */
#define ESPCONN_TIMEOUT    -3    /* Timeout.                 */
#define ESPCONN_RTE        -4    /* Routing problem.         */
#define ESPCONN_INPROGRESS  -5    /* Operation in progress    */

#define ESPCONN_ABRT       -8    /* Connection aborted.      */
#define ESPCONN_RST        -9    /* Connection reset.        */
#define ESPCONN_CLSD       -10   /* Connection closed.       */
#define ESPCONN_CONN       -11   /* Not connected.           */

#define ESPCONN_ARG        -12   /* Illegal argument.        */
#define ESPCONN_ISCONN     -15   /* Already connected.       */

#define ESPCONN_HANDSHAKE  -28   /* ssl handshake failed	 */
#define ESPCONN_SSL_INVALID_DATA  -61   /* ssl application invalid	 */
ハンドシェイクに失敗しているようですがこれでは何もわかりません。さて?

SDK v1.2.0 での AT コマンド拡張内で SSL が機能しない理由

不審に思い情報を探したところ同じ問題に遭遇したユーザとスタッフの応酬に気づきました。

Re: SSL connection via AT commands

Postby doughboy ≫ Tue Apr 21, 2015 11:59 pm

I am writing AT command to support SSL, but it seems none of
the espconn_secure_* api works. 
At least when I connect to real ssl servers using real
cerfificates. (and yes, I have set buffer size to 8196 and
use the patched ssl library) esp module will
reset (I think due to wdt timeout). I already reported this
via email.
Re: SSL connection via AT commands

Postby Espressif_Faye ≫ Mon Apr 27, 2015 10:22 am

Hi, doughboy,

We debugged on your problem, it's the RAM limitation cause that.

AT commands has only 17KBytes available heap now,
SSL need 12KBytes free heap size, 
if you espconn_secure_set_size to set 5KBytes,it is not enough..

So SSL can not be used in AT commands because RAM is limited. 

Sorry for the inconvenience.

AT コマンドプログラム実行時には残ヒープが 17KB 程度だが、SSL 処理には 12KB のヒープが必要で、そこに espconn_secure_set_size() で数 KB の SSL バッファ確保を指定すると完全に枯渇してしまう。そのため、AT コマンドで SSL を扱うことはできない、という話です。

ホストへの接続要求の前に system_print_meminfo() および system_get_free_heap_size() を呼び出してみると次の結果でした。


data  : 0x3ffe8000 ~ 0x3ffe89d8, len: 2520
rodata: 0x3ffe89e0 ~ 0x3ffeabd4, len: 8692
bss   : 0x3ffeabd8 ~ 0x3fff5010, len: 42040
heap  : 0x3fff5010 ~ 0x3fffc000, len: 28656

system_get_free_heap_size=16592 

なるほど。なお、AT コマンドセットは SDK においてはライブラリ形式で供給されており、自作コマンドを追加することはできても既存のものを変更することはできません。

さて?

冒頭に書いたように、ESP-WROOM-02 を通信モジュールとして扱う状況においてはシリアル経由でのコマンド渡しで簡単に通信処理を利用できることには便宜があります。

しかし、そこで SSL を利用できないことは大きなマイナスであり実用を想定すると使途が限定されることになるでしょう。そのため既存の AT コマンドセットに代わるインターフェイス込みでの SSL 処理の実装が必要であり、その方法はいろいろ考えられるもののどうも遠まわりな印象があります。

それはそれとして、一方では ESP-WROOM-02 は自立したマイコンとしての側面も持ち合わせているため、要件によっては単体で処理をまかなうことが可能であるわけで、とどのつまり製品出荷時の AT コマンドセットは「おまけ」程度のものと割り切るべきなのかも?

そんなことを考えながら、SSL 処理そのものが正常に動作することを確認するために前掲のプログラムを AT コマンドセットと切り離し単体で起動する形に変更して動作を試してみました。
ホストへの接続要求前のヒープ状況は以下の通りで、HTTPS リクエストは問題なく処理されました。やはりメモリ不足の問題のようです。


data  : 0x3ffe8000 ~ 0x3ffe8560, len: 1376
rodata: 0x3ffe8560 ~ 0x3ffe9764, len: 4612
bss   : 0x3ffe9768 ~ 0x3fff2b30, len: 37832
heap  : 0x3fff2b30 ~ 0x3fffc000, len: 38096

system_get_free_heap_size=34856

サーバ証明書の検証について

立ち止まっていても仕方がないので、いずれにしても必要となる SSL サーバ証明書の検証に手をつけてみることにしました。

SDK に同梱の「ESP8266 SSL User Manual」には HTTPS クライアント処理においてサーバ証明書を検証する方法が次のように記述されています。

(クリックで実寸表示)

上記ドキュメントからの抜粋

CA verify function default to be disabled, user can enable it
by espconn_secure_ca_enable.

3.1. Generate CA Certificate

(1) Put script “make_cert.py”and CA certificate into
    the same folder. 
(2) Run script “make_cert.py” to generate esp_ca_cert.bin
    which contains all CA certificates
    (2 CA certificates at most) in the same folder. 
    Download address of esp_ca_cert.bin depends on
    espconn_secure_ca_enable.

3.2. CA Verify

STEP 1: ESP8266 connects to server, read esp_ca_cert.bin
        from flash, get the corresponding SSL 
        ctx. Only 2 CA certificates is allowed at most.
STEP 2: ESP8266 starts TLS handshake, get certificate from
        SSL server, check with the CA in step 1:
        • if CA check fail, connection break;
        • if succeed, CA verify pass. 
4.2. espconn_secure_ca_enable

Function: 
  Enable SSL CA (certificate authenticate) function 

Note:
  • CA function is disabled by default 
  • If user want to call this API, please call it before 
                 espconn_secure_accept
                 (ESP8266 as TCP SSL server) or 
                 espconn_secure_connect
                 (ESP8266 as TCP SSL client)
Prototype: 
  bool espconn_secure_ca_enable (uint8 level, uint16 flash_sector) 

Parameter: 
  uint8 level : set configuration forESP8266
                SSL server/client:
                 0x01 SSL client;
                 0x02 SSL server;
                 0x03 both SSL client and SSL server 

  uint16 flash_sector : flash sector in which CA
  (esp_ca_cert.bin) is downloaded. For example, 
  flash_sector is 0x3B, then esp_ca_cert.bin need to
  download into flash 0x3B000

Return:
  true : succeed
  false  : fail 

「make_cert.py」は SDK には含まれません。下記ページにダウンロードリンクが掲載されています。

以下の手順で「https://www.example.com/」のサーバ証明書の検証を試みました。

  • DigiCert のルート証明書をブラウザから X509 形式(DER エンコード)でエクスポートし拡張子を .cer とする
  • *.cer を置いたディレクトリで上記の make_cert.py を実行し「esp_ca_cert.bin」を生成する
  • espconn_secure_connect() の前に下記行を記述しuser1.bin をフラッシュメモリサイズ 1024KB の指定でビルド
    espconn_secure_ca_enable(0x01, 0x65)); // 0x01 = client
  • 他の *.bin ファイルと一緒に、esp_ca_cert.bin をフラッシュメモリの 0x65000 番地(User Data area)を起点に書き込む
    ※ビルドした user1.bin のサイズは 300KB ほどであり余裕をみて 400KB として
    ブート領域の 4KB と合算すると 404KB につき 404 * 1024 = 413696 = 0x65000
    - 下のメモリマップ(再掲)を参照のこと
    ※1024KB フラッシュ使用時のメモリマップ
    
         - SDK の「Espressif IOT SDK User Manual」より
    
    Note 
    
    • System param (system parameter area) is the last 16KB offlash. 
    
    • User param is the user parameter area used by Espressif demo code
      ( IOT_Demo or AT ). If users develop their own application, 
      user data can be saved in any available flash area. 
    
    • User Data area ( green area in pictures below ) means the flash
      area that may be available, if program area doesn’t reach the
      maximum size, remaining area can be used to save user data. 
    
  • 期待通りにサーバ証明書の検証が行われ www.example.com への HTTPS リクエストは正常に処理され、ルート CA が DigiCert ではないサイトへの HTTPS リクエストにおいてはハンドシェイクの時点でエラーとなることを確認

解決:SDK v1.3.0 なら AT コマンド拡張内で SSL 処理が動く!

そうこうしている内に、2015-08-08 に公開された esp_iot_sdk_v1.3.0_15_08_08 のリリースノートの次の記述が目に飛び込んできました。

Optimization:

1.Memory optimization to save 12KBytes.
            :

前述のとおり、SDK v1.2.0 を使ってビルドした AT コマンド拡張版で SSL が機能しなかったのはメモリ不足が原因だったため、v1.3.0 で 12KB 余裕が出来たのであればあるいは動作可能ではないかと考えました。 実際に v1.3.0 でビルドした user1.bin で AT+GETTEST コマンドを試したところ HTTPS リクエストが正常に処理されることを確認、ホストへの接続要求前のヒープ状況は以下の通りでした。まずはめでたし、です。


data  : 0x3ffe8000 ~ 0x3ffe83ac, len: 940
rodata: 0x3ffe83b0 ~ 0x3ffe9d40, len: 6544
bss   : 0x3ffe9d40 ~ 0x3fff18b8, len: 31608
heap  : 0x3fff18b8 ~ 0x3fffc000, len: 42824

system_get_free_heap_size=31376

動作の様子 (動画:2分19秒)

今回試作した GETTEST コマンドは所定のホストに対し "GET /" を行うのみの内容ですが、以上のように大枠での動作を確認できたため今後は任意の URI の指定や POST メソッドへの対応など実用上必要な肉付けを手元で行うことになるでしょう。楽しみです。

上の動画で使用している現時点のファーム一式のうち user1.bin 以外のバイナリを以下のアーカイブに収めています。 自分の環境の AP の SSID とパスワードをソースに記述して user1.bin をビルドし、図の要領でこれらのバイナリ一式を ESP-WROOM-02 のフラッシュメモリに書き込めば AT+GETTEST コマンドが動作するはずです。興味のある方は自己責任でお試し下さい。


(tanabe)

klab_gijutsu2 at 18:00|この記事のURLComments(0)TrackBack(0)
2015年04月21日

「TWE-LITE」ファームウェアプログラミングの試み

はてなブックマークに登録

2017-01-13 追記:
TWE-LITE(旧表記「TWE-Lite」)のメーカーが変わり同社からのリクエストに基づいて関連箇所の改訂を行いました。結果として、2015年4月に公開した元の記事に2017年1月現在の新しい情報やキーワードが部分的に反映された内容となっています。念のため要所に注釈を加えており混乱につながる要素は特に含まれていないと判断していますが、記事参照の際にはご注意下さい。

モノワイヤレス株式会社様の ZigBee 無線マイコンモジュール「TWE-LITE DIP」はコストパフォーマンスが高く人気のある製品です。手軽にノード間の無線通信を実現できるため IoT を構成する要素としても所定の圏内に閉じた機器間ネットワークのための道具立てとしても有用でしょう。
標準のものに加え複数の典型的な用途に即したファームウェア群とそのソースコードが開発環境とともに無償で公開されていることも興味深く、製品はホスト PC から専用の USB アダプタ (TWE-LITE R) または市販の USB シリアル変換モジュール/ケーブル経由で自由にファームを書き換えられるようにデザインされています。

このように単なる通信モジュールではなくプログラマブルなマイコンとしての側面を持ち合わせながら価格が低廉であることが TWE-LITE DIP の大きな魅力です。また、「超簡単!」の惹句の通り出荷時の標準ファームでは扱いやすさが特に重視されており、そういった間口の広さと奥の深さがこの製品の特長と言ってよいでしょう。

試みのきっかけ

TWE-LITE ユーザはメーカーの提示するソフトウェア使用許諾契約書に基づいて TWE-NET SDK を利用することができます。また、規約の認める範囲で公式ファームのソースコードを改変したりその内容を公開することも可能です。

ネットを参照すると現時点では実際に公式ファームに手を加えて TWE-LITE DIP を使っている利用者は製品の人気に比べまだあまり多くないように見受けられます(注:2015年04月時点の記述)。その背景には、まず公式のファームウェア群が充実しているため改変の不要なケースの多いことが想像されますが、それに加えて、精密に記述されている各ファームのボリュームのあるソースコードはその内容を適切に理解しなければ手を触れにくいという事情もあるように思われます。メーカーが公開しているこれらのファームは基本的に実用を目的とするものであって教育用ではありませんから、利用する側はコードの世界をじっくり楽しみながらノウハウを覚えるスタンスに立つことが好ましいでしょう。

ただ、ここしばらく TWE-LITE に触れた印象では、そこに「ちょっとした足がかり」があれば公式ファームのコードをより見渡しやすくなり、そのことがこの優れた製品を手元で活用する機会を拡げることにもつながるように感じました。思い浮かべたのは "Hello, world!" のようにもっとも単純で簡潔な内容からはじまり徐々に処理が肉付けされていくイメージの小さなサンプルファームコード群です。でも残念ながら今のところそういうものは見当たりません(注:2015年04月時点の記述)。そこで、実験と勉強をかねて現時点での自分の到達点なりにそういうコードを書いてみることにしました。一連の過程での疑問点・不明点の解決には言うまでもなく公式ファームのソースと上記の SDK マニュアルが非常に参考になりました。この試みは今後も継続するかもしれませんが、まずはここまでのソースコードと動作の様子を公開します。興味のある方は覗いてみて下さい。

※本記事に掲載のソースコードには公式ファームウェアのソースからの
 引用が含まれます。取り扱いに際しては著作権表記を確認の上、前掲の
 「モノワイヤレスソフトウェア使用許諾契約書」の内容を遵守して下さい。
  なお、本記事での各ソースコードの掲載ならびにメーカー公式サイト上の
  個々のページへの直接のリンク・公式文書からの情報の抜粋については
  いずれも事前にモノワイヤレス様より承諾を得ています。

※本記事の本文および本記事に掲載のソースコードには誤りが含まれて
 いる可能性があります。そのことがいかなる損害に繋がったとしても
 筆者および KLab は一切の責任を負いません。あらかじめご了承下さい。

技術情報について

TWE-LITE 用プログラミングに必要な情報は多岐に渡り、メーカー公式サイトの情報前掲の TWE-NET SDK マニュアル、また、NXP 社製 JN5164 用のペリフェラル (TWE-LITE の I/O ポートまわり) API のマニュアル等が主な情報源となります。後続のソースコードを参照する上で最小限必要なもっとも基本的な資料三点を以下に抜粋します。
※図はクリックで大きく表示されます

TWE-LITE DIP のピン配置   (メーカー公式サイトの「超簡単!TWE標準アプリ」ページより)

TWE-LITE ファームウェアコードの動作フロー   (前掲の SDK マニュアルより)

Test01: LED を点滅させる

まずはマイコン・電子工作の世界での「Hello, world!」にあたる LED の点滅、いわゆる「L チカ」を行います。ネットワーク通信は行いません。

動作の様子

装置の写真と構成図(クリックで大きく表示)

ソースコード  GitHub

ユーザ定義のイベントハンドラ内で 1秒周期の E_EVENT_TICK_SECOND 通知に呼応し出力ポートの Lo, Hi をトグルする

Test02: スイッチ操作に LED の状態を連動させる

上の Test01 は全自動かつエンドレスですが、今度は人間の操作に反応させてみます。タクトスイッチの ON/OFF に LED の点灯/消灯 が連動します。ネットワーク通信は行いません。

動作の様子

装置の写真と構成図(クリックで大きく表示)

ソースコード  GitHub

既定のイベントハンドラ cbToCoNet_vMain() 内でタクトスイッチの状態に応じて LED の状態を変化させる

Test03: シリアル経由でデバッグメッセージを出力

プログラミングにはデバッグのための手段が不可欠です。Test02 のコードに、シリアル接続経由で PC 上のターミナルアプリへトレース文を出力する処理を加えてみます。PC との接続には専用の USB アダプタ 「TWE-LITE R」を使用しています。 (市販の USB シリアル変換モジュール/ケーブルも利用できます ネットワーク通信は行いません。

動作の様子

装置の写真と構成図(クリックで大きく表示)

ソースコード  GitHub

起動時に UART とデバッグ出力用の初期化を行い vfPrintf() 関数を使ってシリアルへトレース文を出力

Test04: スイッチ押下でメッセージを送信 〜 受信側は LED で反応

無線送受信を行います。Test02 の装置と同じものをもうひとつ用意します。タクトスイッチが押下されるとメッセージをブロードキャストし、受信した側は LED を一定時間点灯させます。

動作の様子

装置の写真と構成図(クリックで大きく表示)

ソースコード  GitHub

スイッチ押下時に ToCoNet_bMacTxReq() によりブロードキャストを実行。既定のイベントハンドラ cbToCoNet_vTxEvent() および cbToCoNet_vRxEvent() 内で送受信通知への対応を行う

Test05: 電力消費を抑制した送信専用コードと装置

上記 Test04 での送信処理を独立させ、消費電力を抑えることを目的にメーカー公式の「無線タグアプリ(App_Tag)」(注:2015年04月時点での名称は「Samp_Monitor」)押しボタン・磁気スイッチ対応機能における子機処理(EndDevice_Input)での以下の要所を取り入れた内容です。

  • TWE-LITE のモード設定ビット 1 (M1) が GND に接続されていれば(すなわち M1 が Lo であれば)、デジタル入力 1 (DI1) の立ち上がり (Lo -> Hi) を送信のトリガーとする
    (典型的には平時が導通状態の磁気リードスイッチが磁界から離れ切断された状況)
    • 立ち上がりトリガーの場合 節電のため DI1 の内部プルアップを無効化する。そのためこの場合は外部プルアップ抵抗を設置する。(公式サイト上の記事を参考に 1MΩ 抵抗を使用)
  • M1 が GND に接続されていなければ DI1 の立ち下がり (Hi -> Lo) をトリガーとする
    (典型的には平時が非導通状態のタクトスイッチが押下された状況)

  • 送信を終えたらすみやかに Sleep 状態へ移行し DI1 の状態が変化すると Sleep から復帰する

受信側は Test04 のものをそのまま使います。以下の動画・写真では送信側の装置は磁気リードスイッチを使っており立ち上がり検出を行っています。 ちなみにこの装置の待機(Sleep)状態の消費電流を測ったところ 3μA(0.003mA)でした。一般に CR2032 の放電容量はおよそ 225mAh であることから、下記のサイトを利用して単純計算すると待機継続可能期間は 225mAh / 0.003mA * 0.7 = 52500時間 = 2187.5日 ≒ 5.99年となります。実際の電池寿命は送信頻度によって大きく変わるでしょう。

電池寿命カリキュレータ - www.digikey.jp

動作の様子

装置の写真と構成図(クリックで大きく表示)

ソースコード  GitHub

電源投入直後やリセット後はまずそのまま Sleep 状態へ移行。DI1 の状態が変化すると起床して送信を行いふたたび Sleep へ。DI1 の立ち上がり/立ち下がりのどちらで送信を行うかは M1 の Lo / Hi 状態で決定する

付録:「無線タグアプリ」カスタマイズの記録

2015年4月、手元の実験的要件への対応のために前掲の公式アプリ「無線タグアプリ(App_Tag)」(当時の名称は「Samp_Monitor」)の親機(Parent/)および子機(EndDevice_Input/)コードのカスタマイズを試みました。以下はその記録です。

変更を加えたソース・ヘッダ

※ベースのバージョンは 2015年4月20日当時の最新版「Samp_Monitor v1.4.1 β」です(2017年1月現在は既に公開終了)
※変更箇所は識別子「MODIFIED_BY_KLAB」で区別しています

変更内容

EndDevice_Input:

  • センサモードが PKT_ID_BUTTON(押しボタン・磁気スイッチ) の場合、一度の送信完了でただちにスリープ状態へ移行せず所定の回数繰り返し送信を行ってから移行する (diff)

Parent:

  • 電子ブザーの接続を想定し DO4 の使用を追加。センサモードが PKT_ID_BUTTON の子機からパケットを受信した場合、DO1 の LED トグルに合わせ DO4 の状態もトグルする
  • PKT_ID_BUTTON の子機からの受信発生後は親機がリセットされるまで DO1 の LED を点滅させる(受信有無を事後に目で確認するための便宜) (diff)

以下の動画・写真では子機側の装置は磁気リードスイッチを使用し立ち上がり検出を行っています。したがってこの子機のパラメータ設定において「m:センサ種別の設定」には 0xFE、「p:センサ固有パラメータの設定」には 1 を指定しています。

動作の様子

装置の写真と構成図 上:親機 下:子機 (クリックで大きく表示)

(備考)

2017年1月13日時点での最新版 SDK 「2014/8月号」に収録されている旧 Samp_Monitor v1.3.2 の子機側ソースコードには本来の意図とは異なるものと考えられるロジックが含まれています。

  1. 子機のパラメータ設定内容をセーブ領域から読み出すタイミング
    (/TWESDK/Wks_ToCoNet/Samp_Monitor/EndDevice_Input/Source/EndDevice_Input.c)
    ※ 旧 Samp_Monitor v1.4.1β で改修されました
  2. 子機のセンサモードが PKT_ID_BUTTON (0xFE) の場合の固有パラメータ 立ち上がり (1) / 立ち下がり (0) 指定に対する処理
    (/TWESDK/Wks_ToCoNet/Samp_Monitor/EndDevice_Input/Source/ProcessEv_Button.c)
    ※ 旧 Samp_Monitor v1.3.3 で改修されました

そのため、今の時点で「無線タグアプリ」を使う場合は単体で配布されている版を利用するほうが良いでしょう。


(tanabe)
klab_gijutsu2 at 16:37|この記事のURLComments(18)
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント