元WindowsアプリケーションエンジニアがMilkcocoaを試してみた

JavaScriptもろくに書けない元アプリケーションエンジニアが、IoTをやりたくて、まずはMilkcocoaのお勉強から始めてみました。

# きっかけ
そもそも、画像関連のエンジニアをしていたのですが、最近になってDeep Learningが流行りだしたので、それに伴いデータ送信側のIoTにも興味を持ち始めました。
そこで[IoTLT](https://www.facebook.com/groups/IoTLT/)を知り、参加（見るだけ ^^;）していたところ、「なんかみんな『Milkcocoa』ってのを使っているぞ？」てことで、試してみることにしました。

# Milkcocoaって何よ？
しかし肝心の「Milkcocoa」が何者かよくわかりません。
そこで、[本陣](https://mlkcca.com/)に切り込むことにしました。

．．．よくわからん。

[チュートリアル](https://mlkcca.com/tutorial/page1.html)を見ました。
ようやく理解できました。
タダで使えるキュー（非同期通信）ですね。
![alt](https://mlkcca.com/img/tutorial/method.png)

- タグつけて、データを送る
- タグで監視して、データを受け取る

で、送り側がIoT端末で、受け側がPCだと。（チュートリアルの例）

とりあえず仕組みはわかりましたので、実際に何かサンプルを作ってみることにします。
なお、ホスティングは「[BitBalloon](https://www.bitballoon.com/)」がいいよと書いてあったので、それを使ってみます。
※「BitBalloon」に関しては[こちら](http://uepon.hatenadiary.com/entry/2016/09/16/124942)を参考にさせていただきました。
※実は「[Heroku](https://www.heroku.com/)」も気になっている

# サンプル：画像送信
★★★　まだ動いていません！　★★★

## 目指しているもの

- スマホを傾けると、傾きによって2種類の異なる画像が送られる
- 送られた画像をPC側で取得し、表示する

## 画像の送り方
Milkcocoa経由でバイナリデータを送る方法がわからなかったため、[ここ](http://qiita.com/yasumodev/items/e1708f01ff87692185cd)を参考にして、base64にエンコード／デコードしてみる。

## 送り側（スマホ）

- 最初に2種類の画像を読み込み、base64にエンコードしておく
- スマホを傾けたら、それぞれの画像をMilkcocoaに送る
- 下記ソース以外に「landscape.png」「portrait.png」のファイルを置いておく

```html:index.html
<body>
<img crossOrigin="Anonymous" id="img_landscape" src="./landscape.png" /><br/>
<img crossOrigin="Anonymous" id="img_portrait" src="./portrait.png" /><br/>
<textarea id="log" rows="10" cols="40"></textarea>
<div id="output"></div>
<script src="https://cdn.mlkcca.com/v0.6.0/milkcocoa.js"></script>
<script src="main-sp.js"></script>
</body>
```

```javascript:main-sp.js
window.onload = function(){

  var currentMode = 'portrait';
  var output = document.getElementById('output');

  var img_landscape   = document.getElementById('img_landscape');
  var img_portrait    = document.getElementById('img_portrait');
  var image_landscape = ImageToBase64(img_landscape, "image/png");
  var image_portrait  = ImageToBase64(img_portrait,  "image/png");
  document.getElementById('log').value = image_portrait;

  // app_idは自分のものに書き換えてください
  var milkcocoa = new MilkCocoa('app_id.mlkcca.com');
  var ds = milkcocoa.dataStore('gravity');

  window.addEventListener('devicemotion', function(e){
    gravity = e.accelerationIncludingGravity;

    output.innerHTML
    = 'x方向: '+gravity.x
    + '<br>y方向: '+gravity.y;

    sendModeFromGravityValue(gravity);

  },true);


  function sendModeFromGravityValue(g){

    // 絶対値を取得
    var x = Math.sqrt(g.x * g.x);
    var y = Math.sqrt(g.y * g.y);

    // portrait -> landscape
    if(currentMode === 'portrait' && x > 8.5 && y < 1.5){
      currentMode = 'landscape';
      ds.send({mode: image_landscape});
      document.getElementById('log').value = image_landscape;
    }

    // landscape -> portrait
    if(currentMode === 'landscape' && x < 1.5 && y > 8.5){
      currentMode = 'portrait';
      ds.send({mode: image_portrait});
      document.getElementById('log').value = image_portrait;
    }
  }

  function ImageToBase64(image_src, mime_type) {
    // New Canvas
    var canvas = document.createElement('canvas');
    canvas.width  = image_src.width;
    canvas.height = image_src.height;
    // Draw
    var ctx = canvas.getContext('2d');
    ctx.drawImage(image_src, 0, 0);
    // Image Base64
    return canvas.toDataURL(mime_type);
  }
};
```

## 受け側（PC）

- 送られてくるのを監視し、来たらコールバック関数に飛ばす
- コルバック関数内で「image.src」に直接base64のデータを代入する
- 下記ソース以外に「dummy.png」のファイルを置いておく

```html:index.html
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<title>PC側</title>
</head>
<body>
<img crossOrigin="Anonymous" id="image" src="./dummy.png" />
<textarea id="log" rows="10" cols="40"></textarea>
<script src='https://cdn.mlkcca.com/v0.6.0/milkcocoa.js'></script>
<script src="main-pc.js"></script>
</body>
```

```javascript:main-pc.js
window.onload = function(){

  var image = document.getElementById('image');

  // app_idは自分のものに書き換えてください
  var milkcocoa = new MilkCocoa('app_id.mlkcca.com');
  var ds = milkcocoa.dataStore('gravity');

  ds.on('send', changeViewFromSentMode);

  function changeViewFromSentMode(sent){
    image.src = sent.value.mode;
    document.getElementById('log').value = sent.value.mode;
  }
};
```

## しかし動かない．．．＿|￣|○
「Milkcocoaへの送信」～「Milkcocoaからの受信」のどこかで失敗している模様。
（受信イベントが発火しない）
もしかしたら、送信できるデータのサイズの制限があるのだろうか．．．
（文字数が少ないと、ちゃんと送れることは確認済み）

# 後日談
見つけました。

```
※4KBより大きいメッセージの送信はできません。
```

とのこと。