ゲートウェイ機能仕様書
ゲートウェイはHTTPを利用してセンスデータを受信することによりRFIDのデータを収集します。ゲートウェイとリーダライタはLANにて接続を行いますが、関係は一対一です。複数接続することは出来ません。
プログラム構成
ゲートウェイは主に2つのプログラムで構成されます。
-
Pollingプログラム
RFIDタグRWを制御し、タグ情報をPollingして取得します。
その中で加速度付きのタグがあれば、加速度データが格納されているメモリ領域のデータを取得します。(加速度付きタグは予め指定)
取得したタグ情報はprocessingディレクトリにファイル保存されます。
Pollingプログラムはcronにより10分毎に起動されます。 -
Publisherプログラム
Pollingプログラムがprocessingディレクトリに保存したデータファイルを読み込み、クラウド(GCP IoT Coreサービス)で設定されたPub/SubトピックにPublishします。送信完了したファイルはcompletedディレクトリに移動します。
また、GCP IoT Coreサービスのデバイスの「構成」と「状態」情報の送受信を行います。
「状態」情報として、ゲートウェイ(Raspberry PI)のCPU温度やディスク使用率等のステータス情報送信します。
「構成」情報として、RFIDタグRWのIPアドレス、加速度付きタグリストを受信し、ゲートウェイ内に保存します。
Publisherプログラムは、常駐プロセスとしてゲートウェイ起動時に自動起動されます。
インストールフォルダ構成
/opt/jeweler_amethyst/edge
|-- certificate
| `-- roots.pem
|-- config
| `-- setting.conf
|-- gcp_connect_keys
| |-- rsa_x509_cert.pem
| `-- rsa_x509_private.pem
|-- logo
| `-- farmnote_aa.txt
|-- module
| |-- config.py
| |-- edgelog.py
| |-- gcpmqttclient.py
| |-- rfidrw.py
| `-- rfidtag.py
|-- polling
| |-- cron_polling
| |-- polling.py
| `-- starter.py
|-- publisher
| |-- publisher.py
| |-- publisher.service
| `-- publisher.sh
|-- rfid_rw_ip
| |-- ipaddress
| `-- ipaddress.tmp
`-- rfid_tag_list
|-- accelerometer_tag
`-- accelerometer_tag.tmp
プログラムファイル説明(順不同)
config/setting.conf
Pollingプログラム、Publisherプログラム共通の設定ファイルです。
module/config.py
ライブラリモジュールです。設定ファイル関連処理で使用されます。
polling/polling.py
RFIDタグRWのポーリング、メモリ読込を行いデータファイルとして出力するPollingプログラムです。
polling/starter.py
pollingプログラムを起動するためのプログラムです。cronで10分毎に起動されます。
publisher/publisher.py
pollingプログラムで出力されたデータファイルをGCP IoT Coreに送信(Publish)するPublisherプログラムです。
publisher/publisher.sh
Publisherプログラムをサービス起動する際に使用される起動用スクリプトです。
publisher/publisher.service
Publisherプログラムをサービス登録する際に使用される設定ファイルです。
module/edgelog.py
ライブラリモジュールです。Pollingプログラム、Publisherプログラムのログ出力で使用されます。
module/gcpmqttclient.py
ライブラリモジュールです。PublisherプログラムでGCPとのMQTT通信に使用されます。
module/rfidtag.py
ライブラリモジュールです。PollingプログラムでRFIDタグRWからのデータ取得、タグ通信リトライ処理で使用されます。
module/rfidrw.py
ライブラリモジュールです。PollingプログラムでRFIDタグRWからのデータ取得、及び書き込みで使用されます。
開発言語
Python 3
設定ファイル
[GCP_IOT]
; GCP IoT Core 接続関連
project_id = jeweler-amethyst-dev
cloud_region = asia-east1
registry_id = ja_iot
;device_idの記述がない場合、シリアル番号がデバイスIDとして扱われる
;device_id = ja_dev1
algorithm = RS256
private_key_file = /opt/jeweler_amethyst/edge/gcp_connect_keys/rsa_x509_private.pem
mqtt_bridge_hostname = mqtt.googleapis.com
mqtt_bridge_port = 8883
ca_certs = /opt/jeweler_amethyst/edge/certificate/roots.pem
[RFID_RW]
; RFID リーダライタのアクセスIPアドレス記述ファイル
ip_address_file = /opt/jeweler_amethyst/edge/rfid_rw_ip/ipaddress
; 加速度付きRFIDタグのリスト記述ファイル
accelerometer_tag_file = /opt/jeweler_amethyst/edge/rfid_tag_list/accelerometer_tag
; mem_length:読込単位(10進)
; mem_offset:初期オフセット位置(10進)
; mem_lengthずつオフセットをずらしながらmem_loop_limit回Read処理を繰り返す
; (mem_length * mem_loop_limit + 2) がタグの全データ領域ワード数となるよう設定のこと(2 はコントロールとカウント領域分)
mem_length = 4
mem_loop_limit = 7
mem_bank = 3
; 全メモリ領域クリア時のデータ領域サイズ(control,record_count領域は除く)
; コントロールとカウント領域分は除いたワード数を指定
mem_all_area_length = 30
; メモリRW処理のリトライ回数上限
mem_retry_max = 5
; メモリRW処理のリトライWait秒数(小数でミリ秒指定可)
; Wait秒は最低時間。Wait中に他の処理を行うためWait時間は正確ではない
mem_retry_wait_sec = 1.0
;タグへのテスト用ダミーデータ書込(ON/OFF)
writing_dummy_data = OFF
; 出力ログレベル(CRIT:0 ERR:1 WARN:2 NOTICE:3 INFO:4 DEBUG:5)
log_level = 4
[DATAPATH]
; RFID ポーリングデータファイル配置ディレクトリ
processing = /var/jeweler_amethyst/edge/datafile/processing/
completed = /var/jeweler_amethyst/edge/datafile/completed/
error = /var/jeweler_amethyst/edge/datafile/error/
datafile_limit_days = 14
[PUBLISHER]
connection_refresh_interval_min = 15
subscribe_conf_interval_min = 5
subscribe_command_interval_min = 5
publish_status_interval_min = 10
json_schema_file = ../json_schema/rfid_data.json
jwt_password = eDCF7MFYjShxNb89
; 出力ログレベル(CRIT:0 ERR:1 WARN:2 NOTICE:3 INFO:4 DEBUG:5)
log_level = 4
データ取得手順
【メイン処理】
- RFID RWにPollingコマンドを送信してタグ情報を取得します。
- Polling時刻としてシステム時刻を取得します。
- タグ情報の中から、加速度付きタグリストに含まれるものがあれば加速度情報取得処理(後述)を行い、加速度情報を取得、パースします。
- 取得したタグデータをファイル出力します。
【加速度情報取得処理】
タグのメモリ領域に格納された加速度情報を下記フローで取得します。
なお、メモリ領域のRead/Write処理でエラーとなった場合、設定値mem_retry_maxを上限としてリトライ処理を行います。
-
データ領域の処理判定
(a) control, record countをまとめてReadします。
(b) controlによって次の処理を決定します。
control=0 だった場合:3-(c)へ
control=1 だった場合:2へ
control=2 だった場合:3-(b)へ
controlが上記以外だった場合:5へ -
サンプリングデータ読込
(a) 1で取得したrecord count分、データ領域をReadします。
(b) データクリア処理へ -
データクリア
(a) controlに2をWriteします。
(b) controlに0をWriteします。
(c) record countをReadします。
(d) record count分、データ領域に0をWriteします。
(e) record countに0をWriteします。
(f) サンプリング開始処理へ -
サンプリング開始
(a) controlに1を書き込みます
(b) タグR/W処理完了 -
全データクリア
(a) controlに2をWriteします。
(b) controlに0をWriteします。
(c) countと全データ領域に0をWriteします。
(d) 4へ
- プログラム内で使用するRFID RWコマンド
OpenRd, CloseRd, StartInv, StopInv, Polling, ReadMem, WriteMem
Note
RFID RWコマンドについての詳細はRFID RWのマニュアルを参照してください。
タグデータ取得周期について
設定
- mem_length
メモリ領域をR/Wする際の単位サイズです。 - mem_loop_limit
メモリ領域をR/Wする回数。最大mem_length✕mem_loop_limitの領域が処理されます。 - mem_all_area_length
メモリ領域をオールクリアする際のサイズです。
Note
サイズ指定はwordサイズです(1ワード=2byte)
各項目はcontrol, record count領域は除いた範囲となります。
加速度データ付きデータ領域の展開手順
加速度のデータがあるか否かは、データ領域を実際に読み込んでみた結果により判断します。
読込失敗した場合は、加速度データなしでデータ登録されます。
クラウドへのデータPOST
ポストデータフォーマット
Publisherプログラムがクラウド側へ送信するJSON Schemaと、送信データ例を下記に記載します。
- JSON Schame
{
"$id": "https://example.com/person.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "json schema of RFID tag data",
"type": "object",
"required": ["gateway_id","polling_timestamp","tag_data"],
"properties": {
"gateway_id":{
"description": "Gateway ID",
"type":"string",
"minLength": 8,
"examples":[
"10000000bd8ef2c8-192_168_0_230"
]
},
"polling_timestamp":{
"description": "Timestamp at polling start",
"type":"string",
"examples":[
"2021-03-02T21:32:47.430252+09:00"
]
},
"tag_data":{
"type":"array",
"minItems": 1,
"items": {
"type":"object",
"required": ["tag_type", "ant", "epc", "rssi"],
"properties":{
"tag_type":{
"description": "Type of RFID tag",
"type":"string",
"enum":["epc_only", "accelerometer"]
},
"ant":{
"type":"string",
"examples":["01"]
},
"tsp":{
"type":"string",
"examples":["0001E840"]
},
"rep":{
"type":"string",
"examples":["0184"]
},
"rssi":{
"type":"string",
"examples":["FD75"]
},
"crc":{
"type":"string",
"examples":["04FF"]
},
"pc":{
"type":"string",
"examples":["3000"]
},
"epc":{
"type":"string",
"examples":["E28011606000020549BFF02C"]
},
"data":{
"type":"string",
"examples":["1234123490ABCDEF"]
}
}
}
}
}
}
- 送信データ例
{
"polling_timestamp": "2021-03-25T00:40:02.593754+09:00",
"gateway_id": "10000000c2a21ae5-192_168_0_230",
"tag_data": [
{
"ant": "01",
"tsp": "447978B6",
"rep": "31CE",
"rssi": "FD96",
"crc": "A4D8",
"pc": "3400",
"epc": "300833B2DDD9014000000006",
"tag_type": "accelerometer",
"mem_data": "CBC60E649A43901E0A0CAE4801C39B03CED724D775CAEE7AB12C3DCA0ED034A964255A6BE9998E336E1C93BDC0C82EAE402EB06B9AED6CDC",
"gateway_id": "10000000c2a21ae5-192_168_0_230",
"polling_timestamp": "2021-03-25T00:40:02.593754+09:00"
},
{
"ant": "01",
"tsp": "447978C1",
"rep": "2660",
"rssi": "FD7D",
"crc": "A353",
"pc": "3000",
"epc": "E28011606000020549BFD026",
"tag_type": "epc_only",
"gateway_id": "10000000c2a21ae5-192_168_0_230",
"polling_timestamp": "2021-03-25T00:40:02.593754+09:00"
},
{
"ant": "01",
"tsp": "447978C5",
"rep": "2E48",
"rssi": "FD1D",
"crc": "7418",
"pc": "3000",
"epc": "E28011606000020549BFF02B",
"tag_type": "epc_only",
"gateway_id": "10000000c2a21ae5-192_168_0_230",
"polling_timestamp": "2021-03-25T00:40:02.593754+09:00"
},
]
}
データ保存場所と保持期間
-
未処理データ
/var/jeweler_amethyst/edge/datafile/processing/ -
POST済みデータ
/var/jeweler_amethyst/edge/datafile/completed/
データ送信失敗となった場合、未処理データディレクトリにファイルが残り次回処理時に再送信が行われます。
なお、再送信処理時は新規データを優先して処理されます。
未処理データ、POST済みデータともに1週間記録されます。
Warning
保存先がRAMとなっているため、Raspberry Piの電源がOFFになるとデータが消去されます。
