S0-ma's Blog

s0-maのブログです。

CO2-miniのデータをPython (Mac OSX Mojave) で読み出してみた

Abstract

買ったCO2濃度モニターをMac OSX (Mojave) にUSB接続して、データ取得してみました。

Introduction

CO2-miniという、手頃な値段のCO2センサーを購入した。 s0-ma.hatenablog.com

決め手となったのは、非公式ながらもUSB接続で値が読み取れるという点。 以下が、CO2-miniのリバースエンジニアリングをした人のブログ。なかなか面白い。Pythonを使って、最終的にプロトコルの解析に成功している。

hackaday.io

ただ上記記事の内容はLinuxを想定したコードであるため、そのままだと手元のMac OSX (Mojave)では動作しなかった。Mac OSX上のPythonから値を読み取れるか試してみた。

読み出し

このCO2センサの場合、USBの中でもHID(Human Interface Device)クラスというプロトコルで読み出しができる。Linuxだとデバイスファイル経由で読み書きするのが簡単らしく、CO2-mini用の読み出しコードもそういった実装のものが多く見つかった。ただ、Mac OSXだとデバイスファイルが存在しないので、少しやり方を変える必要がある。

まずは、PythonからHIDデバイスを使うためのライブラリをインストール。

pip install hidapi

実行コードは最終的に以下のようになりました。 ほとんどの部分がオリジナルのブログからの流用です。

#!/usr/bin/python
#-*- coding: utf-8 -*-

import hid
import time
import datetime

key = [0x86, 0x41, 0xc9, 0xa8, 0x7f, 0x41, 0x3c, 0xac]

def decrypt(data):
    cstate = [0x48, 0x74, 0x65, 0x6D, 0x70, 0x39, 0x39, 0x65]
    shuffle = [2, 4, 0, 7, 1, 6, 5, 3]

    phase1 = [0] * 8
    for i, j in enumerate(shuffle):
        phase1[j] = data[i]

    phase2 = [0] * 8
    for i in range(8):
        phase2[i] = phase1[i] ^ key[i]

    phase3 = [0] * 8
    for i in range(8):
        phase3[i] = ((phase2[i] >> 3) | (phase2[(i-1+8)%8] << 5)) & 0xff

    ctmp = [0] * 8
    for i in range(8):
        ctmp[i] = ((cstate[i] >> 4) | (cstate[i]<<4)) & 0xff

    out = [0] * 8
    for i in range(8):
        out[i] = (0x100 + phase3[i] - ctmp[i]) & 0xff

    return out

if __name__=="__main__":
    h = hid.device()
    h.open(0x4d9, 0xa052)
    h.send_feature_report([0x00]+key)

    flg1 = False
    flg2 = False

    while(True):
        buf = h.read(8)
        decrypted = decrypt(buf)
        if decrypted[4] != 0x0d or (sum(decrypted[:3]) & 0xff) != decrypted[3]:
            print("Checksum error")
            break
        else:
            val = decrypted[1] << 8 | decrypted[2]

            if(decrypted[0]==5*16):
                co2 = val
                #print("co2:", co2)
                flg1=True
            elif(decrypted[0]==4*16+2):
                temp = val/16-273.15
                #print("tmp:%.1f" % temp)
                flg2=True
        if(flg1==True and flg2==True):
            print(datetime.datetime.now(), co2, "%.1f"%temp)
            flg1 = False
            flg2 = False

Concolusion

実行結果はこんな感じ。

2019-06-26 22:25:09.452618 478 27.2
2019-06-26 22:25:14.468803 480 27.2

CO2-miniのデータ更新が秒に一回程度らしく、それに合わせたタイミングで取得できる。 CO2濃度の更新は5秒間隔、温度の更新は30秒間隔みたい。

CO2モニター買ってみた

Abstract

CO2濃度モニターを買ってみた。最終的な目標は、CO2濃度のログを定期的に取ること。USB経由でデータが取れて、かつ安価なものを探してみた。

Introduction

会社のとある会議に月イチで参加し始めたのだが、なんだか後半息苦しい。で、ふと思い出したのが以下の記事。

togetter.com

内容としては、教授が『自分の面白い講義を聞いて寝てしまう学生がいるのは講義室のCO2濃度が高いからだ』とCO2モニターを持って講義に出かけたら本当に基準値よりも高かった、という話。

会社の環境改善もそうだけど、単におうちハックとしても面白そうだと思い手軽なCO2濃度モニターを探すことにした。

購入候補

ざっくりと、候補となるCO2濃度センサは以下の三種類に分けられた。

  • センサデバイス単体基盤 (5000円以下)
  • 液晶表示機能付きの卓上センサ (1~5万円)
  • プロ・業務向け (5万円以上)

値段は、調べた個人的な感触。3は高すぎる。1はキャリブレーションを自分でやらなきゃいけないっぽくて、リファレンスを持っていない。温度補償とかも自分で実装するのかな?結果として、2の価格帯でUSB読み出しできるやつを探した。

と、そんな中見つけたのが下の記事。2016年のものだけど、扱っている製品はまだ現役で売られている。 r-kurain.hatenablog.com

これがそのCO2濃度モニタ。1万円を切る価格で、公式にはUSBでの読み出しには対応していないものの、非公式(デバッグ用?)プロトコルが解析されていてUSB経由で値が読み出せるらしい。

Concolusion

というわけで、買ってみました。小さくてなかなか良い感じ。モバイルバッテリーでもそこそこ長時間動く。「会社の会議室の空気悪いなぁ」なんて思った場合に、サクッと値を見せて環境改善を要求するのに使えそう。

f:id:s0-ma:20190622172859j:plain:w300

次回、PythonからCO2濃度と温度を読み出してみようと思います。

スマートミニコンセントをAlexaで制御してみた

Abstract

前回記事では、作業机の上に吊ってあるペンダントライトをスマートライト化するため、Alexa echoに対応したスマートスイッチを買った。 今回は、Smart Lifeというアプリでリモート制御できるようにした後、更にAmazon Alexaと連携させて音声制御までをやってみた。

Introduction

使ったスマートスイッチはこれ。

s0-ma.hatenablog.com

スマートスピーカーは安売りされている時に買って眠っていたAmazon Echoを使いました。

やりかた

スマートミニコンセントとSmart Lifeアプリを連携させるのに手こずったので、その部分だけ詳しく書いてみる。

  1. まずは、Smart Lifeアプリをスマートフォンに導入。アドレス登録とか認証を済ませる。

  2. アプリ右上の「+」ボタンをタップ。
    f:id:s0-ma:20190622162600p:plain:w300

  3. コンセントを選択。
    f:id:s0-ma:20190622162823p:plain:w300

  4. 「デバイスの追加」画面が表示されスマートミニコンセントのLEDを点滅させろと指示があるが、気にせず次に進む。
    f:id:s0-ma:20190622163055p:plain:w300

  5. スマートミニコンセントの接続先となるWiFiルータの情報を入力。
    f:id:s0-ma:20190622164114p:plain:w300

  6. アプリをこの状態にして、スマートミニコンセント本体の電源ボタン5秒以上長押しで、電源ボタン部分のLEDを点滅させる。
    f:id:s0-ma:20190622163349g:plain:w300

  7. 5.で表示されている「確認」ボタンを押下。接続の進捗が表示されるけど、ただのタイマーで実際の進捗とは関係ないみたい。スマートスイッチの点滅が消えた10秒後くらいに突然進捗が100%になるので、焦らず待つこと。
    f:id:s0-ma:20190622163551p:plain:w300

  8. これでSmart Lifeアプリからスイッチが認識される。その後、Amazon alexaアプリと連携させれば良い。Alexaアプリのスマートホームスキルの中でもSmart Lifeは上位に表示されていたので、かなりメジャーなプラットフォームなのかな。

Concousion

こんな感じで、無事音声で制御できるようになりました。

f:id:s0-ma:20190622164704g:plain:w300

Alexa対応した安いスマートスイッチを買ってみた

Abstract

作業机の上に吊ってあるペンダントライトをスマートライト化するため、Alexa echoに対応したスマートスイッチを買ってみた。

Introduction

PCデスクのライトとして、天井からペンダントライトを吊るして使っている。 照明用のコンセントがないため、延長ケーブルとスイッチ付きコンセントを使ってこんな感じ。

f:id:s0-ma:20190622151322j:plain:w200

パナソニック(Panasonic) スイッチ付タップ・W・1コ口 WHS2001WP 【純正パッケージ品】

悪くはないのだけれど、On/Offの度に立ち上がるのが面倒。最近 Echo Dot を買ったので、スマートライト化するためのスマートスイッチを探してみた。

候補

候補品の検索で使ったキーワードは、

  • スマートスイッチ
  • スマートプラグ
  • スマートコンセント

辺り。 Alexa対応を謳って安くて日本向けのコンセント形状のものだと、だいたい下の3系統に絞られた。

どれも2000円以下。他にも見た目がほぼ一緒で価格が違う製品がいくつか見つかった。中身は一緒だったりするのだろうか。

購入

見つけた中で一番安かった

Htwon スマートプラグ Wifi ミニスマートコンセント Alexa Echo/Googleホーム/IFTTT対応 電気スイッチコントロール タイマーコンセント 遠隔操作 スマートスイッチ 音声コントロール 直差しコンセント 日本語説明書付き

を購入。

Wtwonというメーカーのものらしい。パッケージや本体にはロゴ等一切なし。説明書の日本語も若干怪しいけれど、一応使えそうな感じ。

f:id:s0-ma:20190622152255j:plain:w300 f:id:s0-ma:20190622133901j:plain f:id:s0-ma:20190622133914j:plain

とりあえず、手動スイッチとして動作することは確認できました。

Python+openpyxlでPythonからExcelファイルを作ってみた

Abstract

Pythonのopenpyxlというライブラリを使って、pythonからエクセルファイルの作成・編集を行ってみた。

Introduction

仕事ではPythonを使った測定自動化、データ解析を行っている。 次設計工程に伝える際には、これまではPythonで解析した結果をcsv形式にし、更にExcelファイルに貼り付けてレポート化していた。 しかし、データ種が増え解析後データがそこそこの分量になってくるとコピペが面倒だし、何より時間がかかるのが問題だった。

Pythonのopenpyxlというライブラリを使うとPythonからExcelファイルの読み書きができることを知ったので、試してみた。

Setup and Results

Install

pip install openpyxl

コード

新規ファイルの作成

from openpyxl import Workbook
wb = Workbook()
wb.save("sample1.xlsx")

既存ファイルの読み込み

from openpyxl import load_workbook
wb = load_workbook('test.xlsx')

先頭から行を追加

wb = Workbook()
ws = wb.active

headers = ["x", "y1", "y2"]
d =[[1, 2, 3], 
    [50, 60, 70],
    [35, 82, 11]]

ws.append(headers)
for row in d:
    ws.append(row)

Pandasのデータフレームを書き出す場合

wb = Workbook()
ws = wb.active
df = pd.DataFrame(d)
df.columns = headers

for r in dataframe_to_rows(df, index=True, header=True):
    ws.append(r)

for cell in ws['A'] + ws[1]:
    cell.style = 'Pandas'

wb.save("pandas_openpyxl.xlsx")

ワークシートの追加・名前の編集

ws1 = wb.create_sheet("Mysheet")
ws2 = wb.create_sheet("Mysheet", 0) #新規シートの位置を指定

実行結果

cell styleとして'Pandas'を指定した場合には、自動で罫線がかかったファイルが出来上がった。 f:id:s0-ma:20190302200548j:plain

Conclusion

今までcsvに書き出していたデータが、Excel形式にするとシート単位でまとめられるので便利。 罫線は上記の通り、数式やグラフ作成まで対応しているようなのでいろいろと自動化が捗りそう。

Reference

openpyxl.readthedocs.io

github.com

スマートメーターの30分電力値をPythonで可視化してみた

Abstract

取得したでんき家計簿の30分電力データを、Python+plotlyで可視化・分析してみた。

Introduction

以前の記事では、でんき家計簿からスマートメータで計測された30分電力値を取得した。 そのデータを可視化して、どんなことが読み取れるのか分析してみる。

ただ、この記事( 配達空振り、わずか2% 電気使用量でAIが在宅予測 :日本経済新聞) にもあるように、むやみに公開するとプライバシー・セキュリティ上の懸念がある。 万が一を考え、今回は友人に頼んで古めのデータをサンプルとして取らせてもらった。

Setup and Results

読み込むファイル形式

今回読み込んだのは、以前の記事で作ったcsvファイル。 日付と電力値(30分刻み、48データ)が一行になっている。

2016-11-14 ,2.5 ,2.5 , ... ,0.2 ,0.2
2016-11-15 ,0.1 ,2.3 , ... ,0.2 ,0.2
...

プロットする内容

なるべく人間が全体像を俯瞰できるように、ヒートマップでプロットする。

コード

import pandas as pd
import datetime
from plotly.offline import iplot, init_notebook_mode
import plotly.graph_objs as go

df = pd.read_csv("./usage30min.csv", header=None)
df.columns = ["date"] + [datetime.timedelta(hours=i*0.5) for i in range(48)]
df["date"] = pd.to_datetime(df["date"])
df.set_index("date", inplace=True)

init_notebook_mode(connected=True) 

data = [
    go.Heatmap( 
        x = [str(x)[0:-3] for x in df.columns],
        y = df.index,
        z=df.values.tolist(),
        zmin=0,
        zmax=1.5,

        colorscale='Viridis',
    )
]

layout = go.Layout(
    title = "power usage [kWh]",
    xaxis = {
        "title":"Time",
    },   
    yaxis = {
        "title":"Date",
    }, 
    width=600,
    height=800,
)

fig = {"data":data , "layout": layout}
iplot(fig)

実行結果

横軸が時刻、縦軸が下から上へ新しくなる日付になっており、色の濃さで使用電力(kWh)を表している。 赤い矢印は説明のために後から追加したもの。
f:id:s0-ma:20190211235158j:plain

  • 特徴的な、夜中から朝方にかけての毎日の大電力消費。 こんな電力を必要とするのは電気を熱に変えるような場合くらいで、時間的に見てエコキュート
  • 冬場の昼間にも黄色い1kWhを超えるような時間帯が散発している。炊事の湯沸かしやシャワー?
  • 昼間に電気を使っているので、少なくとも一人暮らしや共働き世帯ではない。
  • 夏場の夜間大電力消費時間が短くなっているのは、暑くてお湯を使う頻度が下がるから? (赤線カッコ部分)
  • 朝食・夕食時間帯にも電力消費が上がっている(縦赤矢印部分)。ガスではなくIH?
  • 夏場は昼夜通して0.8 kWhくらいを消費している。エアコンか?夜間も消さずに点けておくタイプらしい。
  • 所々電気を全く使っていない日がある(赤横矢印部分)。正月やGWと一致する日もあるので、泊りがけで外出していた可能性が高い。

Conclusion

週ごとの傾向や詳細を見始めたら、家族構成や曜日ごとの外出時間までわかってしまいそうで分析をやめといた。 スマートメーターで在宅判断+配送効率UPという記事があったが、 30分値ですら思いの外に様々なことが推測できてしまい怖さすらある。

ただ、これを見ながら夜間湯沸かし量や料金契約の最適化をやったら、結構電気代安くなんじゃないかなとも思った。

Reference

github.com Jupyter Notebook Viewer

www.fnn.jp

Plotlyで書いたグラフがGithubで表示されなかったので、nbviewerを使ってみた

Abstract

Githubにコミットした Plotlyで描画したグラフを含むjupyter notebookをwebから見るために、nbviewerを使ってみた。

Introduction

Jupyter notebookをgithubにアップロードすると、matplotlibなどで描画したグラフはそのまま表示される。 しかしPlotlyを使った場合、Githubがiframeに対応していないためグラフが表示されない。

  • 手元のJupyter notebook f:id:s0-ma:20190211170427j:plain

  • Githubにアップロードした結果 f:id:s0-ma:20190211170516j:plain

過去に投稿したPlotlyを使ったjupyter notebookのグラフがgithubだと表示されないので、 nbviewerを使ってみた。

Setup and Results

nbviewerを使ってみる。 f:id:s0-ma:20190211171344j:plain

例えば、 https://github.com/s0-ma/Blog/blob/master/2019-02-09_plotly_heatmap/plotly_heatmap.ipynb
の内容を表示する場合には、githubドメインより先の部分を
https://nbviewer.jupyter.org/github/ につなげて、
https://nbviewer.jupyter.org/github/s0-ma/Blog/blob/master/2019-02-09_plotly_heatmap/plotly_heatmap.ipynb
のようにすれば良い。

実行結果

Plotlyのグラフも表示できた。
https://nbviewer.jupyter.org/github/s0-ma/Blog/blob/master/2019-02-09_plotly_heatmap/plotly_heatmap.ipynb f:id:s0-ma:20190211170900j:plain

Reference

nbviewer.jupyter.org