MQTTでクラウド経由でArduinoに繋いだLCDでEnOcean teach-in IDを表示する構成をラズパイ２を中心に組んでみた。


なんのことですか？という人が世界の99%だということは知ってますw

![lcdsetting.jpg](https://qiita-image-store.s3.amazonaws.com/0/39784/d2db918f-1109-0dea-bd14-8c4b6bcd55d2.jpeg "lcdsetting.jpg")



EnOceanというのはセンサーやスイッチの規格で、太陽電池や圧電素子による微小な電力でセンサーの値を無線で飛ばそうというエナジーハーベストが特徴です。<a href="https://www.enocean.com/en/smart-home-and-home-automation/">ヨーロッパでは公共の施設とかに設置されている事例があるみたい</a>ですね。

＜2015.9.21追記：最近XOceanというEnOceanの通信モジュールをXBeeのソケットでArduinoにつなぐ製品の紹介記事 http://deviceplus.jp/hobby/entry-spinoff001/ を読みました。EnOceanの紹介としてもとても良いと感じましたので、ここに記載させていただきます＞

で、EnOceanのセンサーを買ってみたんですが、これ、IDがバーコードとかでセンサーの表面に書いていないんです。室内の温度分布とか測ろうとおもってたくさんセンサー買ってきたけど、どれがどれやら。。。
最近流行りのBLEだと自分でアドバタイズするみたいですが、EnOceanの場合はアドバタイズを手動でできるボタンがついているので、ボタン（画像の基板右下のほうでピンの隣）が押された時にアドバタイズのパケットを捕獲してLCDで表示できればいいな。と。（その操作をteach inっていうらしいです。詳しくは<a href="https://www.enocean.com/en/home/">enocean.com</a>へお願いしますm(_._)m

![IMG_1916.JPG](https://qiita-image-store.s3.amazonaws.com/0/39784/bf028251-1390-c698-210d-c25cc64268df.jpeg "IMG_1916.JPG")


長いマクラですみません。

## one more tweak via MQTT

しかし実際にはまだひねりがあります。

EnOceanの無線データ（0x00とかを含むバイナリデータ）はUSBドングルのデバイスがシリアルポートに繋いでくれるし、LCDの表示もシリアルポートにつながったArduinoがやってくれるのですが、単純にhexdumpでテキストにするのもつまらないし、元が改行区切りのテキストデータではないので実際にhexdumpをパイプで繋いでも動作しないため、いったんMQTTでクラウド上のワーカープロセスに送って処理してもらうことにしました。そこはFujiを使えばシリアルポートからMQTTにつなぐのは設定ファイル数行編集するだけだし、ワーカープロセスもmqttcliをちょっといじればできてしまうのでした。

- Fuji: https://github.com/shiguredo/fuji
- mqttcli: https://github.com/shirou/mqttcli

## 構成

0. 本体はRaspberry Pi2
	- Fujiインストール済み
	- Ethernet接続
	- EnOcean USBドングル接続
	- USBケーブルでArduinoとシリアル接続
		- ArduinoからI2Cで「Grove starter kit for Arduino」のLCDに接続
1. EnOceanのUSB-シリアルのドングルで受信したデータをFujiでpublish
2. バイナリからhexに変換するMQTTのworkerをかませる
3. workerの変換結果を別のFujiでsubscribe
4. シリアルポート経由で変換結果の文字列をArduinoに送ってLCD表示


## ArduinoでのLCD表示について

参考にしたところ: https://github.com/Seeed-Studio/Sketchbook_Starter_Kit_for_Arduino/tree/master/Grove_RGB_Backlight_LCD

### ArduinoでのLCD表示スクリプト（ほぼサンプルのまんま）

```
/*
  SerialDisplay.ino
  2013 Copyright (c) Seeed Technology Inc.  All right reserved.

  Author:Loovee
  2013-9-18

  Grove - Serial LCD RGB Backlight demo.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <Wire.h>
#include "rgb_lcd.h"

rgb_lcd lcd;
char lastchar;

void setup(){
    // set up the LCD's number of columns and rows:
    lcd.begin(16, 2);
    lcd.setRGB(123, 230, 0);
    // initialize the serial communications:
    Serial.begin(9600);
}

void loop()
{
    // when characters arrive over the serial port...
    if (Serial.available()) 
    {
        // wait a bit for the entire message to arrive
        delay(100);
        // clear the screen
        // read all the available characters
        while (Serial.available() > 0) 
        {
            // display each character to the LCD
            lastchar = Serial.read();
            if (lastchar == 'q') {
              lcd.clear();
            } else {
            lcd.write(lastchar);
            }
        }
    }
}

```

## MQTTの設定

Fujiの設定ファイル`lcd.ini`を以下のように設定してRaspberry pi上で起動

```
./fuji -c lcd.ini
```

### lcd.ini

```
[gateway]

    name = enoceanlcd

[broker "sango/1"]

    host = std1.mqtt.shiguredo.jp
    port = 1883

    username = kgbu@github
    password = password 

    retry_interval = 10
    topic_prefix = kgbu@github


[device "arduino/serial"]

    broker = sango
    qos = 0

    serial = /dev/ttyACM0 
    baud = 9600
    type = lcd

    subscribe = true

[device "enocean/serial"]

    broker = sango
    qos = 0

    serial = /dev/ttyUSB0 
    baud = 57600
    type = EnOcean
```

### worker

mqttcliにpublish時にhexdump変換させる変更を施してmqttlcdとした

```
$ ./mqttlcd sub -t "kgbu@github/raspi2/enocean/EnOcean" | ./mqttlcd pu-t "kgbu@github/raspi2/arduino" -s
```


[github.com/shirou/mqttcliとの主な差分](http://github.com/shirou/mqttcli%E3%81%A8%E3%81%AE%E5%B7%AE%E5%88%86)

```
$ git diff 8f6172c
diff --git a/publish.go b/publish.go
index 94b2514..ce88104 100644
--- a/publish.go
+++ b/publish.go
@@ -2,6 +2,7 @@ package main
 
 import (
        "bufio"
+       "encoding/hex"
        "os"
 
        log "github.com/Sirupsen/logrus"
@@ -38,7 +39,12 @@ func publish(c *cli.Context) {
                // Read from Stdin
                scanner := bufio.NewScanner(os.Stdin)
                for scanner.Scan() {
-                       err = client.Publish(topic, []byte(scanner.Text()), qos, retain, true)
+                        err = client.Publish(topic, []byte(" q"), qos, retain,false)
+                        if err != nil {
+                                log.Error(err)
+                        }
+
+                        err = client.Publish(topic, []byte(hex.EncodeToString(scanner.Bytes())), qos, retain, false)
                        if err != nil {
                                log.Error(err)
                        }
```

### ENOCEAN からのデータをMQTT経由でpublishしたログ

`85 0 10 2 10 155 34 4 0 87 200 0 0 69 8 224 1 41 202`というバイナリのデータが送信されています。

```
DEBU[1041] read partial data: [85 0 10 2 10 155 34 4 0 87 200 0 0 69 8 224 1 41 202 55 144 0 0 0 0 0 0　（省略）0] to sumBuf: [85 0 10 2 10 155 34 4 0 87 200 0 0 69 8 224 1 41 202] 
DEBU[1041] read data to send: [85 0 10 2 10 155 34 4 0 87 200 0 0 69 8 224 1 41 202] 
DEBU[1041] sumBuf cleared: []                           
DEBU[1041] msgBuf to send: [85 0 10 2 10 155 34 4 0 87 200 0 0 69 8 224 1 41 202] 
DEBU[1041] message got: {kgbu@github/enoceantest/beacon/EnOcean} 
DEBU[1041] message published: {kgbu@github/enoceantest/beacon/EnOcean} 
```

### SUBSCRIBER側で受信したデータのログ

途中で改行コードと間違ってデータを分割して送っちゃってるみたいですが、画面クリアのための`q`の文字に続いてhexに変換された文字列が送られています。

```
DEBU[0831] topic:kgbu@github/enoceanlcd/lcd / msg: q    
INFO[0831] msg topic:, kgbu@github/enoceanlcd/lcd / lcd 
INFO[0831] msg reached to device, message.Message{Sender:"sango", Type:"subscribed", Body:[]uint8{0x20, 0x71}, QoS:0x0, Retained:false, BrokerName:"", Topic:"kgbu@github/enoceanlcd/lcd"} 
INFO[0831] written length: 2                            
DEBU[0831] topic:kgbu@github/enoceanlcd/lcd / msg:55000c02 
INFO[0831] msg topic:, kgbu@github/enoceanlcd/lcd / lcd 
INFO[0831] msg reached to device, message.Message{Sender:"sango", Type:"subscribed", Body:[]uint8{0x35, 0x35, 0x30, 0x30, 0x30, 0x63, 0x30, 0x32}, QoS:0x0, Retained:false, BrokerName:"", Topic:"kgbu@github/enoceanlcd/lcd"} 
INFO[0831] written length: 8                            
DEBU[0831] topic:kgbu@github/enoceanlcd/lcd / msg: q    
INFO[0831] msg topic:, kgbu@github/enoceanlcd/lcd / lcd 
INFO[0831] msg reached to device, message.Message{Sender:"sango", Type:"subscribed", Body:[]uint8{0x20, 0x71}, QoS:0x0, Retained:false, BrokerName:"", Topic:"kgbu@github/enoceanlcd/lcd"} 
INFO[0831] written length: 2                            
DEBU[0831] topic:kgbu@github/enoceanlcd/lcd / msg:e6620000040057c808280b8083013790 
INFO[0831] msg topic:, kgbu@github/enoceanlcd/lcd / lcd 
INFO[0831] msg reached to device, message.Message{Sender:"sango", Type:"subscribed", Body:[]uint8{0x65, 0x36, 0x36, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x34, 0x30, 0x30, 0x35, 0x37, 0x63, 0x38, 0x30, 0x38, 0x32, 0x38, 0x30, 0x62, 0x38, 0x30, 0x38, 0x33, 0x30, 0x31, 0x33, 0x37, 0x39, 0x30}, QoS:0x0, Retained:false, BrokerName:"", Topic:"kgbu@github/enoceanlcd/lcd"} 
INFO[0831] written length: 32    
```