OpenBlocks A7を使ってAWSからミサイル発射


# はじめに
愛機Raspberry PIではなく実用で利用できるOpenBlocksをAWSに接続してみました。
本格的なIoT/M2Mのシステムを構築する上でOpenBlocksのようなゲートウェイ機器はとても重要なものになります。


# OpenBlocks A7について
ARMADA 310、メインメモリにDDR3 SDRAM 1Gを搭載しており、出荷時OSとして、Debian GNU/Linuxがインストールされております。
Ethernet2ポート、USB2ポート、RS-232Cが外部インタフェースとして実装されているので、ゲートウェイ機器として充分な機能を有しております。
スペックの詳細は、[ここ]("http://openblocks.plathome.co.jp/products/obs_a/a7/spec.html")をご覧ください。

# 全体構成
せっかくAWSと接続するので、デバイスとクラウドを接続しているシステムにしたかったので、DREAM CHEEKYのUSB Missile LauncherをOpen Blocksに接続してみました。Raspberry PIとの組み合わせでよく見かけると思います。
Raspberry PIと接続して利用する場合、砲台の駆動に電流が足りず、セルフパワー付きUSBハブを介して接続する必要があるのですが、OpenBlocksでは、直接USBポートにMissile Launcherを接続して駆動しても安定して動作しました。

![image1.JPG](https://qiita-image-store.s3.amazonaws.com/0/60724/76d502c3-a894-e5a5-e468-0ff95fd76106.jpeg "image1.JPG")

![image2.png](https://qiita-image-store.s3.amazonaws.com/0/60724/7df2c365-0911-d66b-d278-912520ff4837.png "image2.png")


今回のシステムだと操作するPCから直接MQTTパブリッシュをしても良いのですが、S3 Event NotificationやSNSなどをトリガーとしてLambda Functionを実行し、結果としてデバイスを制御する仕組みを作りたかったためLambdaを導入しております。


# OpenBlocksの設定
まず、OpenBlocksに入って設定を施すため、USBシリアルを使ってMacから接続しました。
Macからシリアル接続は、ターミナルから

% screen /dev/tty.usbserial-FTY0RAZ0 115200

接続できます。ユーザ名とパスワードは、デフォルト値で接続できます。（デフォルトは、マニュアルに掲載されております。）
家庭のネットワーク環境に接続するために、DHCP設定を行います。
% vi /etc/network/interface

auto eth0
iface eth0 inet dhcp

ネット接続した後にパッケージ更新とよく利用するパッケージを一括で導入します。

% aptitude update
% tasksel install standard

USBに接続するMissile LauncherをPythonでコントロールしたかったので[pyusb]("https://github.com/walac/pyusb")とそれに必要なライブラリをインストールします。

% apt-get install libusb-dev
% python setup.py install

動作確認のため以下のコードを実行してみます。

```python:missile-test.py

import time
import usb.core
import usb.util


class Missile(object):
    DOWN = 0x01
    UP = 0x02
    LEFT = 0x04
    RIGHT = 0x08
    FIRE = 0x10
    STOP = 0x20

    def __init__(self):
        self.DEVICE = usb.core.find(idVendor=0x2123, idProduct=0x1010)
        self.DEVICE.set_configuration()

    def send_cmd(self, cmd):
        self.DEVICE.ctrl_transfer(0x21, 0x09, 0, 0,
                         [0x02, cmd, 0x00, 0x00, 0x00, 0x00, 0x00,0x00])

    def send_move(self, cmd, duration_ms):
		self.send_cmd(cmd)
        time.sleep(duration_ms / 1000.0)
        self.send_cmd(self.STOP)

missile = Missile()
missile.send_move(missile.RIGHT, 1000)
missile.send_move(missile.UP, 1000)
missile.send_cmd(missile.FIRE)

```

砲台が右に動作した後上に行き最後に発射されるはずです。

# MQTTブローカーの起動
デバイスとAwSのTier2アーキテクチャで実現したかったのですが、デバイスに対してクラウドから発射コマンドを送信したかったので、プロトコルとしてMQTTを採用し、MQTTブローカーをEC2上に起動することにしました。
MQTTブローカーは、[mosquitto]("http://mosquitto.org/")を使いました。セットアップは以下通りです。

$ cd /etc/yum.repos.d
$ sudo wget http://download.opensuse.org/repositories/home:/oojah:/mqtt/CentOS_CentOS-6/home:oojah:mqtt.repo
$ sudo yum update
$ sudo yum install mosquitto
$ /usr/sbin/mosquitto&

# OpenBlocks上のクライアントアプリ
MQTTサブスクライバをOpenBlocks上で動作させ、受け付けたメッセージを元にミサイルを動作させます。
（異常系などは無視してます。。）

```python:missile.py

import time
import usb.core
import usb.util
import paho.mqtt.client as paho
import json

class Missile(object):

    def __init__(self):
        self.DEVICE = usb.core.find(idVendor=0x2123, idProduct=0x1010)
        self.DEVICE.set_configuration()

    def getCmdcode(self,cmd_str):
        if cmd_str == 'DOWN':
            return 0x01
        elif cmd_str == 'UP':
            return 0x02
        elif cmd_str == 'LEFT':
            return 0x04
        elif cmd_str == 'RIGHT':
            return 0x08
        elif cmd_str == 'FIRE':
            return 0x10
        else:
            #STOP = 0x20
            return 0x20

    def send_cmd(self, cmd):
        self.DEVICE.ctrl_transfer(0x21, 0x09, 0, 0,
                                      [0x02, cmd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])

    def send_move(self, cmd, duration_ms):
        self.send_cmd(cmd)
        time.sleep(duration_ms / 1000.0)
        self.send_cmd(self.STOP)

def on_connect(mqttc, obj, rc):
    print("Connected:"+str(rc))


def on_message(mqttc, obj, msg):
    json_msg = json.loads(msg.payload)
    if json_msg['action'] == 'FIRE':
        missile.send_cmd(missile.getCmdcode(json_msg['action']))
    else:
        missile.send_move(missile.getCmdcode(json_msg['action']), 1000)

def on_subscribe(mqttc, obj, mid, granted_qos):
    print("Subscribed: "+str(mid)+" "+str(granted_qos))


if __name__ == '__main__':
    missile = Missile()
    mqttc = paho.Client()
    mqttc.on_message = on_message
    mqttc.on_connect = on_connect
    mqttc.on_subscribe = on_subscribe

    mqttc.connect("ブローカーのIP", 1883, 60)
    mqttc.subscribe("message", 0)
    mqttc.loop_forever()
    

```

# Lambda Function
Lambda Functionでは、パラメータのコマンドをそのままMQTTにPublishするだけのロジックにしました。

```Javascript:missile.py

console.log('Loading event');
var mqtt = require('mqtt');
exports.handler = function(event, context) {
    var command = {'action':event.action};
    var client = mqtt.createClient(1883,"ブローカーのIP");
    client.publish('message', JSON.stringify(command),function(){
        console.log(JSON.stringify(command));
        client.end();
        context.done(null, 'Done.');
    });
};


```

# まとめ
OpenBlocksは、Raspberry PI同様簡単にロジックや周辺機器との接続ができました。
商用でのシステム作りの要になるブリッジ機器で柔軟な実装ができるのはとても喜ばしいです。
今回の仕組みのエンハンスとしては、OpenBlocksにカメラを付けてS3に写真をアップロードしてミサイルを打つ（？）といったことも容易にできますね！

# 免責
こちらは個人の意見で、所属する企業や団体は関係ありません。