hanecoのブログ

おうちハックやDIYなどについて書いていくと思います。たぶん。

当ブログは移転しました。

Grafanaの温度計パネルを作った

以前、ダイキンのルームエアコンに搭載されている温度センサの値を読み取り、Grafanaで可視化する記事を書きました。

haneco.hatenablog.jp

この時、現在の室温はデフォルトのGaugeパネルを使ったのであんまり温度を表示している雰囲気が出ていなかったので、プラグインを作ってみました。

github.com

本家のPie chartパネルをベースにして作りました。

GrafanaのインターフェースはAngularで作られているようで、初めて触るのでなんか変な部分があったら教えていただけるとありがたいです。

こんな感じで表示できるようになります。
f:id:hanecochang:20171013220930p:plain

デフォルトの配色センスがダサいので、適宜お好きな色に変更してください…。

室温をデータベースに記録して可視化する(Grafana導入編)

前回の続きです。今回はRaspberry Pi 3にGrafanaをインストールし、グラフ化します。

haneco.hatenablog.jp

GrafanaをRapsberry Pi 3にインストール

リポジトリを追加してGrafanaをインストールする

ARM版のパッケージは公式には配布されていないようですが、非公式で公開されている方がいるのでそれを利用します。

curl -sL https://bintray.com/user/downloadSubjectPublicKey?username=bintray | sudo apt-key add -
echo "deb https://dl.bintray.com/fg2it/deb jessie main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
sudo apt-get update
sudo apt-get install grafana

Grafanaを起動する

sudo service grafana-server start
sudo update-rc.d grafana-server defaults

データソースの設定

ブラウザで http://[Raspberry PiIPアドレス]:3000/ にアクセスします。

f:id:hanecochang:20171004153258p:plain

User/Passwordはadmin/adminです。

f:id:hanecochang:20171004153336p:plain

「Add data source」をクリック。

f:id:hanecochang:20171004153454p:plain

こんな感じで設定します。一番上のNameは任意の名前です。設定が正しく済んでデータベースへの接続に成功すると、画像のように緑の背景でメッセージが表示されます。

ダッシュボードの作成

データソースの設定ができたら、ダッシュボードを作成します。左上のアイコン→Dashbords→Newをクリックすると下記の画面に移動します。

f:id:hanecochang:20171004153606p:plain

とりあえず、グラフ化してみます。「Graph」をクリック。

f:id:hanecochang:20171004154038p:plain

空のグラフが表示されます。グラフの上部分、「Panel Title」と表示されているところをクリックすると画像のようなメニューが表示されるので「Edit」をクリック。

f:id:hanecochang:20171004154229p:plain

画面下部の「Metrics」タブで画像のように設定します。設定が正しく行われて値が取得できると、上部にグラフが表示されます。

FROM
temperatureテーブルのデータをすべて取得します。タグで絞り込みを行いたい場合はWHEREの横の+をクリックして条件を設定することができます。
SELECT
field(value)で値を取得、mean()で平均値にします。
GROUP BY
10分間の値をlocationタグでグループ化します。fill(null)は値が記録されていない時間帯のデータをないものとして扱うということで、full(0)にすると0として扱い、fill(previous)だと前の値を使うという意味です。例えばtime(1s)なのに実際のデータが10秒ごとにしかない場合、残りの9秒間のデータをどう表示するかということに関わってきます。

設定が済んだら、右端の×で閉じて画面上部のフロッピーアイコンで保存します。

f:id:hanecochang:20171004160124p:plain

これで室温/外気温の変化を可視化するダッシュボードが作成できました!


今後は、部屋に誰かがいるかどうか・窓が空いているかどうかなど、室温に影響を与えそうな内容も追加して分析できると面白いかなと思います。

室温をデータベースに記録して可視化する(InfluxDB導入編)

エアコンから温度データを取得できるようになったので、このデータをデータベースに記録して後から参照できるようにしたいと思います。
室温の変化や外気温との関係を分析することで効率よくエアコン運用ができるようになる…かどうかはさておき、普段は室温の変化なんてそんなに気にしていませんが可視化するとどうなるのかなと興味があるので。

データベースはMySQLSQL ServerPostgreSQLなどRDBしか使ったことがないのですが、今回は時系列データベースのInfluxDBを使ってみたいと思います。

エアコンのセンサー監視はRaspberry Pi 3で行なっているので、これにインストールして使用します。

また、可視化については最終的にはダッシュボードを自作したいですが、とりあえず仕事でも使ったことのあるGrafanaを使ってサクッと実現させたいと思います。

InfluxDBをRapsberry Pi 3にインストール

リポジトリを追加してInfluxDBをインストール

$ curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add -
$ echo "deb https://repos.influxdata.com/debian jessie stable" | sudo tee /etc/apt/sources.list.d/influxdb.list
deb https://repos.influxdata.com/debian jessie stable
$ sudo apt-get update
$ sudo apt-get install influxdb

InfluxDBを起動

$ sudo systemctl start influxdb

動作確認。

$ curl -sl -I  http://localhost:8086/ping
$  ps aux | grep influx
influxdb  2380  1.1  1.0 800020  9456 ?        Ssl  12:10   0:00 /usr/bin/influxd -config /etc/influxdb/influxdb.conf 
pi        2396  0.0  0.1   5720  1856 pts/0    S+   12:10   0:00 grep --color=auto influx
pi@raspberrypi:~ $  ss -lntp | grep 808
LISTEN     0      128               127.0.0.1:8088                     *:*     
LISTEN     0      128                      :::8086                    :::*     
pi@raspberrypi:~ $ curl -sl -I  http://localhost:8086/ping
HTTP/1.1 204 No Content
Content-Type: application/json
Request-Id: 8eef0538-a7e8-11e7-8001-000000000000
X-Influxdb-Version: 1.3.5
Date: Tue, 03 Oct 2017 03:11:33 GMT

pi@raspberrypi:~ $ curl http://localhost:8086/query?pretty=true --data-urlencode "q=SHOW DATABASES"
{
    "results": [
        {
            "statement_id": 0,
            "series": [
                {
                    "name": "databases",
                    "columns": [
                        "name"
                    ],
                    "values": [
                        [
                            "_internal"
                        ]
                    ]
                }
            ]
        }
    ]
}

データベース作成

CLI経由でsensorという名前のデータベースを作成します。

$ influx
Connected to http://localhost:8086 version 1.3.5
InfluxDB shell version: 1.3.5
> create database sensor
> show databases
name: databases
name
----
_internal
sensor
> exit

データ投入

HTTP経由でデータを投入してみます。

$ curl -i -XPOST 'http://localhost:8086/write?db=sensor' --data-binary 'temperature,location=LDK value=27.0 1434055562000000000'
$ curl -i -XPOST 'http://localhost:8086/write?db=sensor' --data-binary 'temperature,location=屋外 value=26.0 1434055562000000000'

データの確認

投入したデータを確認します。

$ curl -G 'http://localhost:8086/query?pretty=true' --data-urlencode "db=sensor" --data-urlencode "q=SELECT \"value\" FROM \"temperature\" WHERE \"location\"='LDK'"
{
    "results": [
        {
            "statement_id": 0,
            "series": [
                {
                    "name": "temperature",
                    "columns": [
                        "time",
                        "value"
                    ],
                    "values": [
                        [
                            "2015-06-11T20:46:02Z",
                            27
                        ]
                    ]
                }
            ]
        }
    ]
}
$ curl -G 'http://localhost:8086/query?pretty=true' --data-urlencode "db=sensor" --data-urlencode "q=SELECT \"value\" FROM \"temperature\" WHERE \"location\"='屋外'"
{
    "results": [
        {
            "statement_id": 0,
            "series": [
                {
                    "name": "temperature",
                    "columns": [
                        "time",
                        "value"
                    ],
                    "values": [
                        [
                            "2015-06-11T20:46:02Z",
                            26
                        ]
                    ]
                }
            ]
        }
    ]
}

データの削除

$ curl -XPOST 'http://localhost:8086/query?pretty=true' --data-urlencode "db=sensor" --data-urlencode "q=DROP SERIES FROM  \"temperature\""
$ curl -G 'http://localhost:8086/query?pretty=true' --data-urlencode "db=sensor" --data-urlencode "q=SELECT \"value\" FROM \"temperature\""
{
    "results": [
        {
            "statement_id": 0
        }
    ]
}

JavaScriptでセンサーの値を取得してInfluxDBへ投入する

Node.jsでエアコンからセンサーの値を取得してデータを投入します。だいたいこんな感じ。

// エアコンのセンサーから値を取得する
http.get(`http://192.168.11.2/aircon/get_sensor_info`, (response) => {
    let body = '';
    response.setEncoding('utf8');
    
    response.on('data', (chunk) => {
        body += chunk;
    });

    response.on('end', () => {
        // 取得した文字列をオブジェクトに変換
        const sensorValues = {};
        const items = body.split(',');
        const length = items.length;
        for (let i = 0; i < length; i++) {
            const keyVal = items[i].split('=');
            sensorValues[keyVal[0]] = keyVal[1];
        }

        // InfluxDBに室温と外気温をPOSTする
        const timestamp = +(new Date()) * 1000000;
        const postData = `temperature,location=LDK value=${sensorValues.htemp} ${timestamp}
temperature,location=屋外 value=${sensorValues.otemp} ${timestamp}`;
        const options = {
            host: 'localhost',
            port: 8086,
            path: `/write?db=sensor`,
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            }
        };
        const request = http.request(options, (dbResponse) => {
            dbResponse.setEncoding('utf8');

            dbResponse.on('data', (dbResponseData) => {
                console.log(dbResponseData);
            });
        });
        request.on('error', (error) => {
            console.log(error.message);
        });
        request.write(postData);
        request.end();
    });
}).on('error', (error) => {
    console.log(error.message);
});    

実際には、前回作成した室温監視プログラムに機能追加しました。

github.com


次回は、記録したデータの可視化を行います。

ダイキンのルームエアコンでおうちハックする(センサー編)

以下の記事の続きです。

haneco.hatenablog.jp
haneco.hatenablog.jp

今回はセンサーから値を取得してみます。

取得できる値

室温と外気温を取得できます。外気温は室外機のセンサーで取得しているようです。室温センサーはAN80TRP-Wの場合は本体左側にあります。センサー周りがホコリで汚れている場合は正しく取得できないかもしれないので掃除しましょう。

パラメーター 内容
htemp 室温
hhum 室内の湿度
otemp 外気温

このような値が取得できます。

室温がある範囲から外れたら冷暖房の運転を開始したり、外気温より低いのに冷房が動いていたらメールでアラートを送ったりといったことができそうですね。

センサーを利用したプログラム

うちではハムスターを飼っているのですが外出中の室温が心配です。そこで、室温が設定された範囲から外れたら冷暖房の運転を開始し、室温が安定したら運転を停止するプログラムを書いてみました。

github.com

適当なディレクトリに配置し、config/local.jsonに設定値を書き込んだあと

$ cd temperature-checker
$ node index.js

で動作します。

/opt 以下に配置した場合、systemdで動かす場合は以下のようなUnit設定を記載すれば良いと思います。

[Unit]
Description=Temperature checker
After=syslog.target network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/node /opt/temperature-checker/index.js
WorkingDirectory=/opt/temperature-checker
KillMode=process
Restart=always

[Install]
WantedBy=multi-user.target

ダイキンのルームエアコンでおうちハックする(操作編)

パラメーター解析編からの続きです。

haneco.hatenablog.jp

今回は、解析したパラメーターを元に操作を行ってみます。

なお、この記事に書いてある内容を実行することで実際にエアコンの動作を変更することになるので、試してみる場合は自己責任でお願いします。何か問題が起きても一切保障はできません。

取得した情報を加工して設定する

1からパラメーターを組み立てるのは大変なので、取得した情報を加工して設定するのが楽そうです。

幸い、アダプタが知らないパラメーターは無視されるので、/aircon/get_control_info で取得した内容の必要な部分を書き換えて /aircon/set_control_info に投げるのが簡単です。

電源をオンにする

ret=OK,pow=0,mode=3,adv=,stemp=25.0,shum=0,dt1=M,dt2=M,dt3=25.0,dt4=21.0,dt5=21.0,dt7=M,dh1=AUTO,dh2=55,dh3=0,dh4=40,dh5=40,dh7=AUTO,dhh=40,b_mode=3,b_stemp=25.0,b_shum=0,alert=16,stemp_a=,dt1_a=-8.0,dt7_a=-8.0,b_stemp_a=

こんなレスポンスが返ってきた状態から電源をオンにするには、以下のURLにGETを投げるだけで大丈夫です。

http://[エアコンのIPアドレス]/ret=OK&pow=1&mode=3&adv=&stemp=25.0&shum=0&dt1=M&dt2=M&dt3=25.0&dt4=21.0&dt5=21.0&dt7=M&dh1=AUTO&dh2=55&dh3=0&dh4=40&dh5=40&dh7=AUTO&dhh=40&b_mode=3&b_stemp=25.0&b_shum=0&alert=16&stemp_a=&dt1_a=-8.0&dt7_a=-8.0&b_stemp_a=

pow=0をpow=1に書き換えて、,を&に置換しただけですね。軽く試してみるだけならブラウザでアクセスするだけで動作変更されます。LAN内とはいえ、認証も何もないのがちょっと怖いですね…。

電源以外を操作する

あとは解析編の内容を参考にしてリクエストを投げれば適宜運転モードが変更されます。エアコンの電源がオフの状態でも運転モードや温度の設定変更は反映されるので、ダイキンスマートAPPで状態を確認しながらリクエストを投げるとわかりやすいと思います。


次はセンサー編です。

haneco.hatenablog.jp

ダイキンのルームエアコンでおうちハックする(パラメーター解析編)

我が家ではダイキン製ルームエアコンAN80TRP-Wに無線LAN接続アダプターBRP072A41を接続し、iPhoneダイキンスマートAPPをインストールして操作できるようにしています。

これはこれでとても便利に使えているのですが、どうせならHomebridgeを使って「ホーム」アプリに対応させたり、気温などの条件によって動作を自動化させたいと思い、アプリと無線LANアダプターの通信内容を解析してハックしてみることにしました。

解析方法

大抵の場合はHTTPを使っているに違いない、ということで今回はmitmproxyを使って解析してみます。

mitmproxyのインストール方法は公式サイトを参考に。私はMacを使っているので

$ brew install mitmproxy

でインストールしました。

インストールしたら、

$ mitmproxy

で起動し、iPhoneの設定アプリからWi-Fi→使用中のSSID→プロキシを構成の順に進んでいき、mitmproxyをインストールしたマシンのIPアドレスとポート番号(通常は8080、ターミナル画面右下に表示されている)を入力します。

その後、ダイキンスマートAPPを起動してエアコンの情報を取得します。

f:id:hanecochang:20170929213414p:plain

バッチリ取れました。

その後は(電気代を気にしつつ)色々操作をしながら通信内容を解析していきます。

エンドポイント

APIのエンドポイントは以下の通り。と言ってもRESTfulではなくリクエストはすべてGETで行われているようで、レスポンスはキーと値を=で繋いだコンマ区切りのフォーマットです。

パス 内容
/aircon/get_sensor_info センサの情報。気温とか湿度とか。
/aircon/get_control_info 設定情報。運転モードとか。
/aircon/set_control_info 設定情報の変更。「?」以降にクエリ文字列を付加してリクエストを送るとエアコンの動作を制御できる。
/common/basic_info 基本的な情報。IDやパスワードまで返ってくる(!)ので取扱注意。
/common/get_datetime 現在日時。
/aircon/get_scdltimer_body?target=c ウィークリータイマーの設定情報。

基本的な操作だけなら上3つを使用するだけで良さそうです。

レスポンス解析

/aircon/get_control_info にアクセスすると以下のようなレスポンスを取得できます。

ret=OK,pow=0,mode=3,adv=,stemp=25.0,shum=0,dt1=M,dt2=M,dt3=25.0,dt4=20.0,dt5=20.0,dt7=M,dh1=AUTO,dh2=55,dh3=0,dh4=0,dh5=0,dh7=AUTO,dhh=40,b_mode=3,b_stemp=25.0,b_shum=0,alert=16,stemp_a=,dt1_a=0,dt7_a=0,b_stemp_a=

さっぱりワケが分かりませんが、エアコンの動作を変更しながら少しずつ解析を進めてみました。なお、アプリを使わなくても普通にブラウザからアクセスするだけで取得できます。

pow

電源状態です。0でオフ、1でオンです。

mode

動作モードです。

設定値 内容
1 自動
2 除湿
3 冷房
4 暖房
5 不明
6 送風
7 自動
HUM 加湿

どの動作モードにしても5になることがありませんでした。一部の機種で使われているのでしょうか?詳細は不明です。

1と7が自動ですが、7は自動モードで温度を上げたり下げたりする際に使われるモードのようです。

加湿だけ突然アルファベットになるところがなかなかアレですね。

dt*

それぞれのモードに対して設定されている温度です。

設定値 内容 自動(dt1) 除湿(dt2) 冷房(dt3) 暖房(dt4) 不明(dt5) 自動(dt7)
M 自動
14 14
15 15
16 16
17 17
18 18
19 19
20 20
21 21
22 22
23 23
24 24
25 25
26 26
27 27
28 28
29 29
30 30
31 31
32 32


なぜか除湿モードも値が設定されています。今回解析した範囲ではM以外にはなることはありませんでした。また、dt5はdt4と同じ設定値が使われているようです。暖房の温度を変更するとdt5の値も変更されました。

dh*

それぞれのモードに対して設定されている湿度です。

設定値 内容 自動(dh1) 除湿(dh2) 冷房(dh3) 暖房(dh4) 不明(dh5) 自動(dh7) 加湿(dhh)
0 OFF
40 40%
45 45%
50 50%
55 55%
60 60%
CONTINUE 連続
AUTO_L 低め
AUTO 標準
AUTO_H 高め

dt5と同じくdh5はdt4と同じ値が設定されるようです。

stemp

現在の動作モードで設定されている温度です。dt*の値と同一になります。

shum

現在の動作モードで設定されている湿度です。dh*の値と同一になります。

dt1_a, dt7a_, stemp_a

自動運転モードで「温度を下げる」「温度を上げる」の操作をした場合に値が設定されます。操作した回数に応じて、-8.0〜8.0の値が設定されました。

adv

不明。今回の解析では値が設定されることはありませんでした。

alert

不明。

b_mode=7, b_shum=AUTO, b_stemp=M, b_stemp_a

不明ですが、今回の解析ではb_なしのパラメータと同じ値が設定されているようでした。


次は操作編に続きます。

haneco.hatenablog.jp

にほんブログ村 IT技術ブログ ライフハックへ にほんブログ村 住まいブログ DIYへ にほんブログ村 花・園芸ブログへ