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

## この記事について

[前回構築したPrivate LoRa GW](https://qiita.com/Saito5656/items/99e5646408f256accd8c)に接続するLoRa DeviceをラズパイとLoRaHATで構築します。下図の色付き部分です。

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

させます。

<br>

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/17ce64d8-32e3-d31d-46a6-187863bc679c.png>

<br>

## デバイス

### 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）](https://dragon-torch.tech/cat-components/extension-boards/dth-rplr/)
[(こちらとPiZero/Zero2でも可能です：Raspberry Pi Zero用LoRa HAT)](https://dragon-torch.tech/cat-components/extension-boards/dth-rpzlr/)

* [データシート](https://dragon-torch.tech/wp-content/uploads/2024/04/data_sheet_Rev1.6.pdf)
* [HAT用説明書・サンプルコード](https://dragon-torch.tech/wp-content/uploads/2022/08/E220-900T22SJP_LoRaHAT_Guide_Rev1.zip)

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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/981f3ddd-b67a-319d-223d-fbf59be0f6ca.png)

### LoRa用アンテナ

[TX915-JKS-20](https://www.switch-science.com/products/8676?_pos=2&_sid=88851d8ff&_ss=r)


## ラズパイ LoRa Device

### ラズパイ基本環境

GW同様に[過去記事](https://qiita.com/Saito5656/items/62e46f009000991b2adf#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)の環境から必要に応じて追加/削除します。

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

```sh:追加の操作
#シリアルポート有効化
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と同じにします。

```sh:/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

にします。

```python: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に従い以下の順に操作します。

```sh
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を先に起動して待ち受けさせておきます。

```sh: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

```sh:/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されているのが確認できます。

```sh: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出来ているのが確認できました。

<img width= 700 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565396/d577a9ba-4256-313d-b1a4-8172c521add9.png>

## 次回

[Private LoRa Gateway経由でnodeのデータをAWS IoTにpublish③ E220でESP32 LoRaデバイス構築](https://qiita.com/Saito5656/items/ff984905995e31a596ef)

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