0
0
お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

Private LoRa Gateway経由でnodeのデータをAWS IoTにpublish② E220でラズパイLoRaデバイス構築

Last updated at Posted at 2024-07-07

この記事について

前回構築したPrivate LoRa GWに接続するLoRa DeviceをラズパイとLoRaHATで構築します。下図の色付き部分です。

  • edge node用ラズパイにLoRaHATを装着しPrivate LoRaデバイス化
  • edge node用ラズパイを仮想エッジデバイスと見立てて監視対象の数値をLoRa GWにpub

させます。



デバイス

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)
(こちらとPiZero/Zero2でも可能です:Raspberry Pi Zero用LoRa HAT)

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

リンク先の画像です
image.png

LoRa用アンテナ

TX915-JKS-20

ラズパイ LoRa Device

ラズパイ基本環境

GW同様に過去記事の環境から必要に応じて追加/削除します。

wiringpiがよろしくないですが今回はこのまま使います。

追加の操作
#シリアルポート有効化
sudo raspi-config nonint do_serial 2
#ライブラリ追加
pip install pyserial wiringpi

LoRa通信parameters

zipに含まれるE220-900T22S(JP)_シンプルLoRaHAT_利用ガイド_Rev1.pdfに従い以下の設定にします。暗号化はありにします。

own_address

前回Pi GWでは0に設定したので今回のPi LoRa Deviceは1にします

その他のparameter

暗号化キー含めて前回のPi GWと同じにします。

/home/user/config_code/setting.ini
[E220-900JP]
own_address=1
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 Device

/home/user/operation_code/send.pyを流用してE220デバイス間Private LoRa通信用のsubscriberをプロトタイプしました。

このラズパイ LoRa Deviceの

  • 識別子(device_no):1
  • 監視対象の値(何でもイイdummy):8888

にします。

send.py(修正後)
import serial
import sys
import argparse
import hexdump


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("-p", "--payload_length")
    parser.add_argument("-a", "--ascii_text")
    parser.add_argument("-f", "--fixed_mode", action="store_true")
    parser.add_argument("--target_address")
    parser.add_argument("--target_channel")
    args = parser.parse_args()

    return args

def main(device_no, msg):
    args = get_args()

    if args.model == "E220-900JP":
        if args.fixed_mode:
            if (args.target_address != None) and (args.target_channel != None):
                t_addr = int(args.target_address)
                t_addr_H = t_addr >> 8
                t_addr_L = t_addr & 0xFF
                t_ch = int(args.target_channel)
                payload = bytes([t_addr_H, t_addr_L, t_ch])
                print("payload:", payload)
            else:
                print("INVALID")
                return
        else:
            payload = bytes([])
            print("payload:", payload)

        if args.payload_length != None:
            count = int(args.payload_length) // 256
            print("COUNT:", count)
            if count > 0:
                payload = payload + bytes(range(256))
                print("payload:", payload)
                for i in range(count - 1):
                    payload = payload + bytes(range(256))
                    print("payload:", payload)
                payload = payload + bytes(range(int(args.payload_length) % 256))
                print("payload:", payload)
            else:
                payload = payload + bytes(range(int(args.payload_length)))
                print("payload:", payload)
        elif args.ascii_text == None:
            payload = payload + f"{msg}\n{device_no}\n".encode()
        else:
            std_in = sys.stdin.buffer.read()
            print("stdin:", std_in)
            payload = payload + std_in
            payload = payload + f"{msg}\n{device_no}\n".encode()
            print("payload:", payload)

        print("serial port:")
        print(args.serial_port)

        print("payload:")
        print(payload)

        print("send data hex dump:")
        hexdump.hexdump(payload)

        with serial.Serial(args.serial_port, int(args.baud), timeout=None) as ser:
            while True:
                if ser.out_waiting == 0:
                    break
            ser.write(payload)
            ser.flush()
            print("SENDED")
    else:
        print("INVALID")
        return


if __name__ == "__main__":
    # このラズパイDeviceの識別子
    device_no = "1"
    # dummy message
    msg = "8888"
    main(device_no, msg)

起動

send.pyでpubする場合も、前回のgateway.py(receive.py)同様にconfig modeでparameterをloadしてからoperation modeに移行してpublisherを起動する必要があります。

E220-900T22S(JP)_シンプルLoRaHAT_利用ガイド_Rev1.pdfに従い以下の順に操作します。

cd ./config_code
python mode3_org.py
python config_cui.py /dev/ttyS0 --apply
cd ../operation_code
python mode0_org.py

while true
do
  python send.py /dev/ttyS0 -f --target_address 0 --target_channel 0
  sleep 10
done

publihserとGW brokerが両方準備できたので前回構築したgateway.pyを先に起動して待ち受けさせておきます。

gateway.py
user@privateLoRaAP1:~ $ python main.py /dev/ttyS0 --rssi
serial port:
/dev/ttyS0
receive waiting...
payload: b''
Connected

/home/user/operation_code/から10秒毎にsend.pyを実行します。

SENDEDっていうのは私じゃないんで…スルーしますので見なかったことにしてあげてくださいm(__)m

/operation_cod/send.py
user@privateLoRaSub1:~/operation_code $  

while true
do
  python send.py /dev/ttyS0 -f --target_address 0 --target_channel 0
  sleep 10
done

payload: b'\x00\x00\x00'
serial port:
/dev/ttyS0
payload:
b'\x00\x00\x008888\n1\n'
send data hex dump:
00000000: 00 00 00 38 38 38 38 0A  31 0A                    ...8888.1.
SENDED

GW brokerで"8888"がsubされているのが確認できます。

gateway.py
.
.
.
topic:  privateLoRaAP1/LoRaDev1
count :  8888
{'Timestamp': 1720206874, 'count': 8888}
topic:  privateLoRaAP1/LoRaDev1
count :  8888
{'Timestamp': 1720206885, 'count': 8888}

AWS IoT CoreのMQTTクライアントでもdevice_no:1(topic:privateLoRaAP1/LoRaDev1)から"8888"がsub出来ているのが確認できました。

次回

Private LoRa Gateway経由でnodeのデータをAWS IoTにpublish③ E220でESP32 LoRaデバイス構築

次回はESP32版のedge nodeでラズパイPrivate LoRa Deviceを構築します。

0
0
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
0
0