Milkcocoa+mbed OS5

この記事は[Milkcocoa Advent Calendar 2016](http://qiita.com/advent-calendar/2016/milkcocoa)の22日目の記事です。

##Milkcocoaについて
私のようなWebに詳しくない人でも[Milkcocoa](https://mlkcca.com/)はインターネットを介して、リアルタイムにWebページや機器を連動させることが簡単にできるのでとても良いです。

##mbed + Milkcocoa
そんなMilkcocoaを使い始めたのは１年ほど前で、mbedのライブラリを作ったのがきっかけです。(mbedについて、詳しく知りたい方は[ここ](https://developer.mbed.org/users/nxpfan/notebook/links_4_mbed_primer/)や[ここ](https://developer.mbed.org/users/okini3939/notebook/mbed_vs_arduino/)を参考にして下さい。私が書いた[書籍](http://www.shoeisha.co.jp/book/detail/9784798142531)もありますｗ)

作ったmbed向けのMilkcocoaライブラリは3種類のサンプルプログラムがあり、ネットに繋ぐインターフェースによって異なります。


---------------------------------------
無線LAN（ESP8266）用
 [https://developer.mbed.org/users/jksoft/code/MilkcocoaSampleESP8266/](https://developer.mbed.org/users/jksoft/code/MilkcocoaSampleESP8266/)

有線LAN用 
[https://developer.mbed.org/users/jksoft/code/MilkcocoaSample_Eth/](https://developer.mbed.org/users/jksoft/code/MilkcocoaSample_Eth/)

３G用 
[https://developer.mbed.org/users/jksoft/code/MilkcocoaSample_3G/](https://developer.mbed.org/users/jksoft/code/MilkcocoaSample_3G/)

---------------------------------------


サンプルプログラムは導入しやすいようにArduino向けのサンプルと同じような作りにしています。

```main.cpp
#include "mbed.h"
#include "MQTTESP8266.h"
#include "MQTTClient.h"
#include "SoftSerialSendOnry.h"
#include "Milkcocoa.h"
#include "MClient.h"
 
// The default setting is for the Simple IoT Board(mbed LPC1114FN28)
// Please change to fit the platform
SoftSerialSendOnry pc(dp10); // tx
DigitalOut myled(dp18);
 
/************************* WiFi Access Point *********************************/
 
#define WLAN_SSID       "...SSID..."
#define WLAN_PASS       "...PASS..."
 
/************************* Your Milkcocoa Setup *********************************/
 
#define MILKCOCOA_APP_ID      "...YOUR_MILKCOCOA_APP_ID..."
#define MILKCOCOA_DATASTORE   "esp8266"
 
/************* Milkcocoa Setup (you don't need to change this!) ******************/
 
#define MILKCOCOA_SERVERPORT  1883
 
/************ Global State (you don't need to change this!) ******************/
 
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
// The default setting is for the Simple IoT Board(mbed LPC1114FN28)
// Please change to fit the platform
MQTTESP8266 ipstack(dp16,dp15,dp26,WLAN_SSID,WLAN_PASS); // TX,RX,Reset,SSID,Password,Baud
MClient client(&ipstack);
 
const char MQTT_SERVER[]  = MILKCOCOA_APP_ID ".mlkcca.com";
const char MQTT_CLIENTID[] = __TIME__ MILKCOCOA_APP_ID;
 
Milkcocoa milkcocoa = Milkcocoa(&client, MQTT_SERVER, MILKCOCOA_SERVERPORT, MILKCOCOA_APP_ID, MQTT_CLIENTID);
 
extern void onpush(MQTT::MessageData& md);
 
int main() {
// void setup() {
    pc.baud(9600);
    pc.printf("Milkcocoa mbed ver demo\n\r\n\r\n\r");
    pc.printf("Connecting to %s\n\r",WLAN_SSID);
    milkcocoa.connect();
    pc.printf("\n\rWiFi connected\n\r");
    
    pc.printf("%d\n\r",milkcocoa.on(MILKCOCOA_DATASTORE, "push", onpush));
    
// }
    while(1) {
// void loop() {
        milkcocoa.loop();
        
        DataElement elem = DataElement();
        elem.setValue("v", 1);
        
        milkcocoa.push(MILKCOCOA_DATASTORE, elem);
        wait(7.0);
    }
}
 
void onpush(MQTT::MessageData& md)
{
    MQTT::Message &message = md.message;
    DataElement de = DataElement((char*)message.payload);
    pc.printf("onpush\n\r");
    pc.printf("%d\n\r",de.getInt("v"));
}
```


また、コンポーネントライブラリにも登録されています。
[<img width="1216" alt="スクリーンショット 2016-12-21 22.57.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/109992/dbf3f273-1af8-b22a-270e-b35b5d7394ee.png">](https://developer.mbed.org/components/cat/online-services/)

##mbed OS5 + Milkcocoa
mbedの中では昨年から今年にかけてmbed OSというものが開発されていて、現在ではmbed OS5が最新になっています。
mbed OS5には次のようなリアルタイムOSのサービスもあり、現在、これらの機能を使って、mbed OS5対応のMilkcocoaライブラリを作成中です。

---------------------------------------
mbed OS5のリアルタイムOSサービス
〇Thread（スレッド）
<img alt="thread_status" src="https://docs.mbed.com/docs/mbed-os-api-reference/en/5.3/APIs/tasks/Images/Thread/thread_status.png">
・並行処理っぽいフローが作れる
・main関数も１つのスレッド
・各スレッドに対して優先順位を設定できる
・main以外のスレッドの動的メモリはスタックで扱われる
・スタックのサイズはデフォルト２KB（環境によって異なる場合あり）
・スレッド内でメモリをたくさん使うクラス等を動的に確保するとスタックが足らなくなるかも

■Mutex（ミューテックス）、Semaphore（セマフォ）、Signals（シグナル）
<img alt="Mutex" src="https://docs.mbed.com/docs/mbed-os-api-reference/en/5.3/APIs/tasks/Images/Thread/Mutex.png">
<img alt="Semaphore" src="https://docs.mbed.com/docs/mbed-os-api-reference/en/5.3/APIs/tasks/Images/Thread/Semaphore.png">
スレッドのフローを制御するための機能他のスレッドの処理を待ったり、共有リソースを使用するタイミングをコントロールしたり。

●Queue（キュー）、Mail（メール）
<img alt="queue" src="https://docs.mbed.com/docs/mbed-os-api-reference/en/5.3/APIs/tasks/Images/Thread/queue.png">
<img alt="mail_queue" src="https://docs.mbed.com/docs/mbed-os-api-reference/en/5.3/APIs/tasks/Images/Thread/mail_queue.png">
スレッド間でデータをやり取りするための機能
排他的に非同期でデータを交換できる

---------------------------------------

どんな風になるかというと・・。

現在のMilkcocoaライブラリはこんなイメージです。
<img width="952" alt="スクリーンショット 2016-12-21 23.19.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/109992/77ff7f27-3546-89a1-276f-9f39a7a42ceb.png">


単機能な機器であればあまり気にならないかもしれませんが、いろんな機能を実現する際にはMilkcocoaのアップするデータを作る処理やMilkcocoaから取得したデータを扱う処理のタイミングはあまり自由にならないので問題になります。

そこでmbed OS5のリアルタイムOSの機能を使うとこんな風になります。
<img width="512" alt="スクリーンショット 2016-12-21 23.24.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/109992/d4977943-24a7-45f1-6bd7-f4e76eca8021.png">

複数のスレッドを使って、メインの処理とWi-Fi通信、Milkcocoaとの通信処理を分離し、シグナルで同期し、キューでデータをやり取りするようにする予定です。
こうすることによって、〜処理〜の部分のタイミングは自由になります。

完成したら公開しますので、もうしばらくお待ち下さい。
（本記事は既出ネタの書き直しです。すみません^^）