この記事について
AWS IoTにデータ転送するためのPrivate LoRa GWとLoRa Deviceの構築手順を3回に分けて記録します。
まず本稿ではラズパイに
- LoRaHATを装着しPrivate LoRaデバイス化
- インターネット経由ではpahoを使いAWS IoTとMQTT
を実装してPrivate LoRa gatewayを構築します。下図の色付き部分です。

昨年夏休みを溶かしてLoRaWANとPrivate LoRaを構築しましたが、Privateは没ネタとなったので記憶から消える前に備忘録を残したいと思います。
デバイス
RaspberryPi
Raspberry Pi: Raspberry Pi 4 Model B Rev 1.2
OS: Raspberry Pi OS Lite 64-bit (Debian GNU/Linux 11 (bullseye))
LoRaHAT
Raspberry Pi 3,4用LoRa HAT(DTH-RPLR)
zipのサンプルコードにはconfig_codeとoperation_codeの二つのdirectoryが入っていますのでラズパイの/home/user/にコピーして使います。
型名 DTH-RPLR
RFモジュール LoRa通信モジュール(E220-900T22S(JP))
通信モジュールの仕様はこちら>>
対応ボード Raspberry Pi 3,4
インターフェース UART
モード制御I/O (信号レベルは3.3V TTL)
電源電圧 動作定格 3.3V ~ 5.5V
推奨電圧範囲 3.5V ~ 5.0V
動作温度範囲 -45℃ ~ +85℃
外形寸法 56mm x 65mm
LoRa用アンテナ
LoRa Gateway
ラズパイ基本環境
過去記事の環境から必要に応じて追加/削除します。
wiringpiがよろしくないですが今回はこのまま使います。
#シリアルポート有効化
sudo raspi-config nonint do_serial 2
#ライブラリ追加
pip install pyserial wiringpi
AWS IoTリソース
過去記事同様に証明書、Thing、policyを作成して証明書はラズパイの/home/user/certに保存します。
LoRa通信parameters
zipに含まれるE220-900T22S(JP)_シンプルLoRaHAT_利用ガイド_Rev1.pdfに従い以下の設定にします。暗号化はありにします。
[E220-900JP]
own_address=0
baud_rate=9600
bw=125
sf=9
subpacket_size=200
rssi_ambient_noise_flag=0
transmitting_power=13
own_channel=0
rssi_byte_flag=1
transmission_method_type=2
wor_cycle=3000
encryption_key=1234
LoRa Gateway + MQTT broker
/home/user/operation_code/receive.pyに手を加えて、
- E220デバイス間でのPrivate LoRa通信をsubする
- subしたpayloadをAWS IoT Coreにpubする
LoRa Gateway + MQTT brokerにしました。
import serial
import time
import argparse
import hexdump
import paho.mqtt.client as mqtt
import json
import ssl
import sys
import os
#####################################################################
# MQTT/aws IoT core settings
#####################################################################
HOSTNAME = os.uname()[1]
# AWS IoT core
host = 'xxxxxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com' # AWS IoT Endpoint
port = 8883 # port
cacert = './cert/AmazonRootCA1.pem' # root ca
clientCert = './cert/privateLoRaAP1-certificate.pem.crt' # certificate
clientKey = './cert/privateLoRaAP1-private.pem.key' # private key
clientid = HOSTNAME
# MQTT base topic settings
topic = HOSTNAME # topic
#####################################################################
#publisherを立てる際のコールバック関数
def on_connect(client, userdata, flags, respons_code):
print('Connected')
#MQTTクライアントを起動してオブジェクト作成する関数
def aws_connect():
try:
client = mqtt.Client(client_id=clientid, protocol=mqtt.MQTTv311)
# certifications
client.tls_set(
cacert,
certfile=clientCert,
keyfile=clientKey,
tls_version=ssl.PROTOCOL_TLSv1_2)
client.tls_insecure_set(True)
# callback
client.on_connect = on_connect
# port, keepalive
client.connect(host, port=port, keepalive=60)
client.loop_start()
except KeyboardInterrupt:
sys.exit()
return client
def publish(client, topic, body):
client.publish(topic, json.dumps(json.loads(body), default=json_serial), qos=1) # publish
print(f"JSON body Published to AWS IoT with topic:{topic}")
return
def json_serial(obj):
return obj.isoformat()
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument("serial_port")
parser.add_argument("-b", "--baud", default="9600")
parser.add_argument("-m", "--model", default="E220-900JP")
parser.add_argument("--rssi", action="store_true")
args = parser.parse_args()
return args
def main():
client = aws_connect()
args = get_args()
if args.model == "E220-900JP":
print(f"serial port: {args.serial_port}")
print("receive waiting...")
with serial.Serial(args.serial_port, int(args.baud), timeout=None) as ser:
payload = bytes()
print("payload:", payload)
while True:
if ser.in_waiting != 0:
payload = payload + ser.read()
elif ser.in_waiting == 0 and len(payload) != 0:
time.sleep(0.010)
if ser.in_waiting == 0:
body = {}
body['Timestamp'] = int(time.time())
print("payload:", payload)
payload_str = payload.decode(encoding='utf-8', errors='replace')
dev_no = payload_str.split("\n")[1]
payload_str = payload_str.split("\n")[0]
print("dev No.: ", dev_no)
topicx = topic + "/LoRaDev" + dev_no
print("topic: ", topicx)
count = payload_str.strip('\x00\n')
print("count : ", count, type(count))
body['count'] = count
print("body : ", body)
publish(client, topicx, json.dumps(body))
if args.rssi:
rssi = int(payload[-1]) - 256
print(f"RSSI: {rssi} dBm")
print("RECEIVED\n")
payload = bytes()
print("payload:", payload)
else:
print("INVALID")
return
if __name__ == "__main__":
time.sleep(10)
main()
起動
E220 moduleでLoRa通信するにはconfig modeでparameterをloadしてからoperation modeに移行してGW + brokerを起動する必要があります。
こちらもE220-900T22S(JP)_シンプルLoRaHAT_利用ガイド_Rev1.pdfに従い以下の順に操作します。
cd ./config_code
python mode3.py
python config_cui.py /dev/ttyS0 --apply
sleep 10
python mode0.py
sleep 5
cd
python gateway.py /dev/ttyS0 --rssi
以下のような画面となればAWS IoTと接続完了してLoRa NW向けには待ち受けの状態になっています。
~ $ python gateway.py /dev/ttyS0 --rssi
serial port: /dev/ttyS0
receive waiting...
payload: b''
Connected
次回
Private LoRa Gateway経由でnodeのデータをAWS IoTにpublish② E220でラズパイLoRaデバイス構築
次回はedge nodeでの利用を想定したラズパイPrivate LoRa Deviceを構築します。