4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

EnOceanの環境発電型ドア開閉センサー(STM250J)の情報をPythonで拾い、内容をESP3に従い解釈する。

Posted at

動機・目的

目的

EnOceanの環境発電型ドア開閉センサー(STM250J)の情報をラズパイで拾って、拾ったデータをESP3、ERP2に従い解釈をする。

動機

「環境発電」という単語を最近耳にすることが多くなってきたので、環境発電を利用して何かサービスめいたものが作成できないか検討する途中で、EnOceanの製品をご紹介いただいので実際に使ってみようと思い立った。

環境

ラズパイ:Raspberry Pi 3 Model B
OS:Raspbian 9
電文受信:USB400J(USB受信ドングル)
センサー:STM250J(ドア開閉センサー)

ラズパイにUSB400Jを刺してセンサーの情報を拾います。Raspbianをインストールしネットワーク設定が完了した後、各パッケージのアップデート完了後から作業を開始しています。ラズパイに入っているPythonのバージョンは2.7.13でした。

物はこちらで購入させていただきました。

実施内容

Pythonで受信した情報を解釈する

以下のソースでUSB400Jの受信している情報を確認し解釈します。
飛んできているデータはEnOcean Serial Protocol 3 (ESP3)というプロトコルに従ったものが飛んでくるので、仕様に従い解釈します。

USB400Jtest2.py
# coding: UTF-8

import serial
import binascii
import threading

class Esp3:
    data_length = 0
    data = bytearray(0)
    option_length = 0
    option = bytearray(0)
    packet_type = b'\x00'
    crc8_header = b'\x00'
    crc8_data = b'\x00'

    def print_data(self):
        print('data_length:%s' % self.data_length)
        print('data:%s' % binascii.hexlify(self.data))
        print('option length:%s' % self.option_length)
        print('option:%s' % binascii.hexlify(self.option))
        print('packet type:%s' % binascii.hexlify(self.packet_type))
        print('crc8 header:%s' % binascii.hexlify(self.crc8_header))
        print('crc8 data:%s' % binascii.hexlify(self.crc8_data))

class Erp2Thread(threading.Thread):

    def __init__(self, esp3):
        super(Erp2Thread, self).__init__()
        self.esp3 = esp3

    def run(self):

        sub_telegram = self.esp3.option[0] #オプションからSub Telegramを取り出す。Send: 3 / receive: 1
        dbm = self.esp3.option[1] * (-1) #オプションからdBmを取り出す。正負反転させる

        erp2_header = self.esp3.data[0] #データからヘッダーとなる1バイトを取り出す

        if erp2_header == ord(b'\x21'): #Originator-ID 32 bit nio Destination-ID、No extended header、1BS telegram のものだけ処理する
            originator_id = binascii.hexlify(self.esp3.data[1:5]) #データからセンサーIDを取り出す
            status_code = self.esp3.data[5] #データからセンサーのステータスを取り出す
            button_status = ""
            door_status = ""


            if status_code == ord(b'\x09'):  #センサーのステータスを人間が解る言葉に翻訳する。STM250Jはcloseとopenだけだが、ボタンのセンサーも同様のプロトコルらしい
                button_status = "押されていません。"
                door_status = "閉まっています。"
            elif status_code == ord(b'\x08'):
                button_status = "押されていません。"
                door_status = "開いています。"
            elif status_code == ord(b'\x01'):
                button_status = "押されています。"
                door_status = "閉まっています。"
            elif status_code == ord(b'\x00'):
                button_status = "押されています。"
                door_status = "開いています。"

            print( 'センサーID:%sは%s' % (originator_id , door_status) )

def main():
    ser = serial.Serial('/dev/ttyUSB0',57600,timeout = 1)

    sync_start = False
    while True:

        denbun = ser.read()
        esp3 = Esp3()

        if sync_start or denbun == b'\x55':   #0x55で同期開始
            sync_start = True

            denbun = ser.read()    #データ長を読み込み
            data_length = 256 * ord(denbun)
            denbun = ser.read()
            data_length = data_length + ord(denbun)

            esp3.data_length = data_length

            denbun = ser.read()   #オプション長を読み込み
            option_length = ord(denbun)

            esp3.option_length = option_length

            denbun = ser.read()  #パケットタイプを読み込み
            packet_type = denbun

            esp3.packet_type = packet_type

            denbun = ser.read() #CRC8(Header)を読み込み
            crc8_header = denbun

            esp3.crc8_header = crc8_header

            data = bytearray(data_length)
            for loop_counter in range(data_length):
                denbun = ser.read() #データを読み込む、長さ分読み込む
                data[loop_counter ] = denbun

            esp3.data = data

            option = bytearray(option_length)
            for loop_counter in range(option_length):
                denbun = ser.read() #オプションんを読み込む、長さ分読み込む
                option[loop_counter] = denbun

            esp3.option = option

            denbun = ser.read() #CRC8(Data)を読み込み
            crc8_data = denbun

            esp3.crc8_data = crc8_data

            sync_start = False

        if esp3.packet_type == b'\x0A':  #パケットタイプがERP2のものだけスレッドで処理する

            erp2_thread = Erp2Thread(esp3)

            erp2_thread.start()

main()

実行結果は以下の通りです。センサーとマグネットを近づけたり遠ざけたりすると表示されます。同時接続も可能です。

センサーID:0400e559は閉まっています。
センサーID:0400e559は開いています。
センサーID:0400e559は閉まっています。
センサーID:0400e559は開いています。
センサーID:0400e6aeは閉まっています。
センサーID:0400e563は閉まっています。
センサーID:0400e559は閉まっています。
センサーID:0400e6aeは開いています。
センサーID:0400e563は開いています。
センサーID:0400e559は開いています。
センサーID:0400e559は閉まっています。
センサーID:0400e6aeは閉まっています。
センサーID:0400e6aeは開いています。
センサーID:0400e559は開いています。
センサーID:0400e6aeは閉まっています。
センサーID:0400e563は閉まっています。
センサーID:0400e559は閉まっています。
センサーID:0400e559は開いています。
センサーID:0400e563は開いています。
センサーID:0400e6aeは開いています。
センサーID:0400e6aeは閉まっています。
センサーID:0400e563は閉まっています。
センサーID:0400e6aeは開いています。
センサーID:0400e563は開いています。
センサーID:0400e563は閉まっています。
センサーID:0400e6aeは閉まっています。
センサーID:0400e559は閉まっています。
センサーID:0400e6aeは開いています。
センサーID:0400e563は開いています。
センサーID:0400e559は開いています。

解説

EnOcean系の製品は複数の仕様にまたがって作られています。
階層的なイメージでとらえていただくと解りやすいかもしれません。一番上のプロトコルがESP3になっています。
今回使用したSTM250JというセンサーはERP2(EnOcean Radio Protocol 2)という下位プロトコルを使用しているので、パケットタイプを識別してERP2のデータだけを処理しています。
センサーが送ってくるデータの実装はEEP(EnOcean Equipment Profiles)という仕様に基づき実装されているので、ERP2で受信したデータをEEPに基づき解釈しています。

解釈のイメージを図で表すとこのようになります。WS000046.JPG

詳細は仕様は公式のドキュメントをご参照ください。

参照ドキュメント

ESP3の仕様
ERP2の仕様
EEPの仕様

感想・今後

想像以上に長いソースになってしまいました。あと仕様を理解するのに時間がかかりました。
センサーのステータスは取得できるようになったので、あとはサービスを提供するサーバへデータを飛ばしていきます。

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?