CO2-miniのデータをPython (Mac OSX Mojave) で読み出してみた
Abstract
買ったCO2濃度モニターをMac OSX (Mojave) にUSB接続して、データ取得してみました。
Introduction
CO2-miniという、手頃な値段のCO2センサーを購入した。 s0-ma.hatenablog.com
決め手となったのは、非公式ながらもUSB接続で値が読み取れるという点。 以下が、CO2-miniのリバースエンジニアリングをした人のブログ。なかなか面白い。Pythonを使って、最終的にプロトコルの解析に成功している。
ただ上記記事の内容は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秒間隔みたい。