ติดตั้งและใช้งาน The Things Stack บน Raspberry Pi 4

Somsak Lima
7 min readApr 22, 2023

--

1.ติดตั้ง Raspbian, Docker, Portainer ให้เรียบร้อย ตามบทความ “การใช้ Raspberry Pi เบื้องต้น” ที่เขียนมาก่อนหน้านี้ หากต้องการติดตั้ง Raspbain 64 bit ให้ทำตามข้อ 56

2.ติดตั้ง Portainer บน Raspbian 64bit

docker pull portainer/portainer-ce:linux-arm64
sudo docker run -d --restart always -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:linux-arm64

เรียกใช้โดยใช้ Port 9000
http://[RASPBERRY_PI_IP_ADDRESS]:9000

ตั้ง User Name/Password admin/ยาว 8/12 ตัวอักษร
เช่น admin/m2mlorawan หรือ m2mlorawan123

คลิก ICON รูปเรือ

3.ติดตั้ง The Things Stack

sudo su
cd
git clone https://github.com/xoseperez/the-things-stack-docker.git

เปลี่ยนเป็น root
ย้ายพื้นที่ทำงานไปที่ /root
clone โปรแกรมติดตั้งใช้คำสั่ง git clone

แก้ไขไฟล์ docker-compose.yml

cd the-things-stack-docker
pico docker-compose.yml

แก้ TTS_DOMAIN จาก lns.example.com เป็น Domain ของเราหรือใส่ 192.168.1.100 เป็นต้น เริ่มติดตั้งโดยใช้คำสั่ง docker-compose up

**** เปลี่ยน IP Server จาก 192.168.1.100 แก้ตรงนี้ด้วย

sudo docker-compose up -d

ถ้าติดตั้งเรียบร้อยจะเห็น Containers ทำงานบน Portainer ตามภาพ

เรียกใช้งาน TTS ได้จาก https://192.168.1.100

หมายเหตุ หากไม่ลงทะเบียนใบรับรอง Electronic จะมีข้อความเวป ไม่ปลอดภัยและ https: สีแดง ถ้าเรียก http อาจจะ login ไม่ได้ แม้จะป้อน user name และ password ถูกต้อง

login ด้วย Default user admin
password changeme

4.เพิ่มผู้ใช้งาน

ใช้ User management เพิ่มชื่อผู้ใช้งาน

Password Test123456 เป็นต้น

ดู Version TTS เข้าที่ Network Information ใต้ Admin Panel

5. Register Gateway

login โดยใช้ user name และ Password ที่สร้างขึ้น

เลือก Go to gateway

Gateway EUI ให้ Copy มาจาก LoRaWAN Gateway หน้าเวป admin
Frequency Plan ให้เลือก Asia 923–925 Mhz

6.สร้าง Application

เลือก Go to applications

คลิก + Create application ด้านขวา

ป้อนข้อมูลแล้วคลิก Create application

7.เพิ่ม End Devices หรือ Node

สมมุติว่าใช้ Rejeee Temp & Humid Sensor

7.1 การดูค่า Config ที่ตั้งไว้ในตัวอุปกรณ์ Sensor

ใช้โปรแกรม Sensor tool เพื่ออ่านค่าความถี่ในการส่งข้อมูล ค่า Key ต่างๆ คือ DevEUI, AppEUI, Appkey ซึ่งจะเก็บไว้ในหน่วยความจำของอุปกรณ์ ให้ใช้สาย USB Type C เสียบเข้ากับ Sensor และให้ Download Sensor tools ได้จากเวป http://doc.rejeee.com/web/#/29?page_id=200 สามารถตั้งค่าอื่นๆ อีก เช่น ค่า Uplink Period กรณีตั้งไว้ 600 วินาที หรือ คือ 10 นาที ซึ่ง Sensor นี้จะส่งข้อมูลทุก 10 นาที เป็นต้น

หรือ

เรียกใช้โปรแกรมแล้วเลือก com port ที่ต่อกับ Sensor เลือกเสร็จให้คลิก Open UART แล้วคลิก ReadConfig ด้านล่าง

จะเห็น DevEUI, AppEUI, Appkey เพื่อนำไปเพิ่ม Device ตามตัวอย่าง เช่น

AppEUI CACBB80000000001 (JoinEUI)

DevEUI CACBB8010000322F

AppKey 11223344556677889900AABBCCDDEEFF

7.2 เพื่ม End Device

เลือก Application ที่จะสร้าง Node ก่อน

คลิก + Register end devices ด้านขวาสีน้ำเงิน

คลิก Show Advanced เพื่อให้มี option เลือก OTAAหรือ ABP และ เลือก Class ของ End Device

ถ้าเป็น End device ที่ไม่มีอยู่ในฐานข้อมูล TTS ให้เพิ่มแบบ Manual
คลิกหน้า Enter end device specifics manually

เลือกความถี่ Asia 923–925 Mhz
เลือก LoRaWAN Version 1.0.3 เป็นต้น

AppEUI CACBB80000000001 (JoinEUI)

DevEUI CACBB8010000322C

AppKey 11223344556677889900AABBCCDDEEFF

ใส่ JoinEUI (AppEUI) หรือ Device EUI, AppKey ให้ครบ

ถ้าเชื่อมได้ปรกติจะเห็น Live Data และ Last Activity แจ้งให้ทราบ

7.3 แก้ Payload format

แก้ Uplink payload format

function decodeUplink(input) {
var obj = {};
var warnings = [];
obj.battery = (input.bytes[1]&0x1F);
obj.vol = (input.bytes[2]);
obj.temperature = (((input.bytes[4] & 0x80 ? input.bytes[4] — 0x100 : input.bytes[4]) << 8)
+
input.bytes[5]) / 10;
obj.humidity = input.bytes[7];
if (obj.temperature < -10) {
warnings.push(“it’s cold”);
}
return {
data: obj,
warnings: warnings
};
}

วิธีดึงค่าจาก TTN มาเก็บไว้บน Privated Influxdb

sudo su ให้เป็น root แล้วสร้างไฟล์ telegraf.conf ให้มีข้อมูลดังต่อไปนี้

[agent]
interval = "10s"
round_interval = true
metric_batch_size = 1000
metric_buffer_limit = 10000
collection_jitter = "0s"
flush_interval = "10s"
flush_jitter = "0s"
precision = ""
hostname = ""
omit_hostname = false


[[outputs.influxdb_v2]]
urls = ["http://192.168.1.100:8086"]
token = "E0g0g2pFytdfYIFSKRAAqSzRyHxqEmUe6mDmrBCqn1ktPChOerSKIGEZhL441zNdXi425s1SIyR5vmMkN1pSJg=="
organization = "Influxdata"
bucket = "tablerejeeetelegraf"


[[inputs.mqtt_consumer]]
name_override = "TTN"
servers = ["tcp://192.168.1.100:1883"]
qos = 0
connection_timeout = "30s"
topics = [ "v3/rejeetemphumid/devices/+/up" ]
client_id = "ttn"
username = "rejeetemphumid"
password = "NNSXS.MVH24AKZLBJTDHC7F2V7M6SACCPUZ4HNU4HTZGY.X234AW7R32BG74JGQ7PZGLUS3YQAQR2RKZDEBO5AYLDGDXY4HJFQ"
data_format = "json"

อื่นๆ ดูได้จากบทความ “Rejeee Temp & Humid Sensor ใช้กับ TTS V3 และ Private Influxdb

ไฟล์ telegraf.conf จะมีสามส่วนหลักๆ คือ
1.กำหนดค่าทั่วไป
2.กำหนดค่าสำหรับดึงข้อมูล (Input)
3.กำหนดค่าสำหรับเขียนข้อมูล(Output)

Input Parameters

[[inputs.mqtt_consumer]]
name_override = "TTN"
servers = ["tcp://192.168.1.100:1883"]
qos = 0
connection_timeout = "30s"
topics = [ "v3/rejeetemphumid/devices/+/up" ]
client_id = "ttn"
username = "rejeetemphumid"
password = "NNSXS.MVH24AKZLBJTDHC7F2V7M6SACCPUZ4HNU4HTZGY.X234AW7R32BG74JGQ7PZGLUS3YQAQR2RKZDEBO5AYLDGDXY4HJFQ"
data_format = "json"

จะได้มาจาก TTS V.3 ในส่วน MQTT Integrations ของ Device

แก้ Server = ให้ตรงกับ IP ของเครื่องที่ลง TTS
ค่าที่ต้องใช้คือ username และ password
User Name จะนำไปแทรกใน topics ด้วย เช่น
topics = [ “v3/rejeetemphumid/devices/+/up” ]

Output Parameters

จะได้มาจาก Influxdb

[[outputs.influxdb_v2]]
urls = ["http://192.168.1.100:8086"]
token = "E0g0g2pFytdfYIFSKRAAqSzRyHxqEmUe6mDmrBCqn1ktPChOerSKIGEZhL441zNdXi425s1SIyR5vmMkN1pSJg=="
organization = "Influxdata"
bucket = "tablerejeeetelegraf"

แก้ organization เปิด influxdb htpp://192.168.1.100:8086 ดู Organization ที่ About

สร้าง bucket เตรียมไว้ก่อนแล้วนำชื่อ bucket มาใช้

คลิกที่ Load Data และ Buckets แล้วเลือก + CREATE BUCKET

Token ให้สร้างจาก ICON Load Data แล้วเลือก API Tokens สร้างแล้วให้นำมาใส่ใน telegraf.conf

หลังจากเป็น root แล้วสร้างและแก้ไขไฟล์ telegraf.conf เสร็จให้สร้าง Container Docker ด้วย root แล้วใช้คำสั่งดังต่อไปนี้ (ไม่ต้อง pull หรือโหลด image ก่อน docker จะโหลดให้อัตโนมัติเมื่อไม่มี image)

docker run -d \
--name=telegraf \
--hostname=telegraf \
--user telegraf:$(stat -c '%g' /var/run/docker.sock) \
-p 8125:8125/udp \
-p 8092:8092/udp \
-p 8094:8094 \
-v $PWD/telegraf.conf:/etc/telegraf/telegraf.conf:ro \
-v /var/run/docker.sock:/var/run/docker.sock \
-e TZ=Etc/GMT+7 \
--restart unless-stopped \
telegraf

วิธีดูข้อมูลใน Influxdb

ข้อมูลจะไปอยู่ในชื่อ Bucket ที่เราเลือก และ Measurement อยู่ ใน client_id เช่น ttn ที่เรากำหนด

เข้า ICON รูปกราฟ Data Explorer ด้านซ้าย ใต้คำว่า Filter เลือก _field แล้วลองคลิก uplink_message_decode_temperature , uplink_message_decode_humid, uplink_message_decode_temperature_battery เป็นต้น แล้วคลิก Submit เลือกช่วงเวลาที่ต้องการดู เช่น Past 12h เป็นต้น

นอกจากนั้นยังมี Field อื่นๆ อีกหลาย Filed ซึ่งมาจาก Metadata ของ Gateway

เราสามารถสร้าง Dashboard ใน Influxdb ได้ตามรูป

** หมายเหตุ อาจติดตั้งด้วย Portainer Template ใช้ Template จาก

https://raw.githubusercontent.com/RAKWireless/portainer-templates/master/portainer_app_template.json

หรือ

stack:
image: xoseperez/the-things-stack:latest
container_name: stack
restart: unless-stopped
depends_on:
- redis
- postgres
networks:
- bridge
volumes:
- 'stack-blob:/srv/ttn-lorawan/public/blob'
- 'stack-data:/srv/data'
environment:
TTS_DOMAIN: 10.249.197.175
CLI_AUTO_LOGIN: "true"
TTN_LW_BLOB_LOCAL_DIRECTORY: /srv/ttn-lorawan/public/blob
TTN_LW_REDIS_ADDRESS: redis:6379
TTN_LW_IS_DATABASE_URI: postgres://root:root@postgres:5432/ttn_lorawan?sslmode=disable
WAIT_HOSTS: redis:6379, postgres:5432
WAIT_HOSTS_TIMEOUT: 300
WAIT_SLEEP_INTERVAL: 30
WAIT_HOST_CONNECT_TIMEOUT: 30

ports:
- "80:1885"
- "443:8885"
- "1881:1881"
- "1882:1882"
- "1883:1883"
- "1884:1884"
- "1885:1885"
- "1887:1887"
- "8881:8881"
- "8882:8882"
- "8883:8883"
- "8884:8884"
- "8885:8885"
- "8887:8887"
- "1700:1700/udp"

Note1.

"categories": [
"LoRaWAN"
],
"description": "This project deploys UDP Packet Forwarder protocol for LoRa 2.4GHz Gateways using Docker. It runs on any amd64/x86_64 PC, or a SBC like a Raspberry Pi 3/4, Compute Module 3/4 or balenaFin.",
"post_up_info": "Please check the Github repository https://github.com/RAKWireless/udp-packet-forwarder for more details.",
"note": "Check <a href='https://github.com/RAKWireless/udp-packet-forwarder'>LoRaWAN UDP Packet Forwarder Protocol for Docker Github repository</a> for more details.",
"image": "xoseperez/2g4-packet-forwarder:latest",
"logo": "https://raw.githubusercontent.com/RAKWireless/portainer-templates/master/logo/gateway_logo.png",
"name": "2g4PacketForwarder",
"title": "2.4GHz Gateway UDP Packet Forwarder",
"hostname": "2g4-packet-forwarder",
"platform": "linux",
"restart_policy": "unless-stopped",
"type": 1,
"env": [
{
"default": "1000",
"label": "PUID",
"name": "PUID"
},
{
"default": "100",
"label": "PGID",
"name": "PGID"
},
{
"default": "Europe/London",
"label": "Time Zone",
"name": "TZ"
},
{
"name": "Device",
"default": "/dev/ttyACM0",
"label": "Concentrator port",
"description": "Where the concentrator is connected to."
},
{
"name": "TTN_REGION",
"label": "TTN region",
"default": "eu1",
"description": "If using a TTN server, region of the TTN server to use. Can be eu1, nam1, and au1"
},
{
"name": "SERVER_HOST",
"label": "Host Server URL",
"description": "If TTN_REGION is defined it will build the right address for the TTN server"
},
{
"name": "SERVER_PORT",
"label": "Server port",
"default": "1700",
"description": "Port the server is listening to"
},
{
"name": "GPS_LATITUDE",
"label": "GPS LATITUDE",
"description": "Report this latitude for the gateway"
},
{
"name": "GPS_LONGITUDE",
"label": "GPS LONGITUDE",
"description": "Report this longitude for the gateway"
},
{
"name": "GPS_ALTITUDE",
"label": "GPS ALTITUDE",
"description": "Report this altitude for the gateway"
}
]
},

Note2.

version: '2'

volumes:
redis:
postgres:
stack-blob:
stack-data:

services:

postgres:
image: postgres:14.3-alpine3.15
container_name: postgres
restart: unless-stopped
environment:
- POSTGRES_PASSWORD=root
- POSTGRES_USER=root
- POSTGRES_DB=ttn_lorawan
volumes:
- 'postgres:/var/lib/postgresql/data'
ports:
- "127.0.0.1:5432:5432"

redis:
image: redis:7.0.0-alpine3.15
container_name: redis
command: redis-server --appendonly yes
restart: unless-stopped
volumes:
- 'redis:/data'
ports:
- "127.0.0.1:6379:6379"

stack:
image: xoseperez/the-things-stack:latest
#build:
# context: .
# args:
# ARCH: arm64
# REMOTE_TAG: 3.27.2
container_name: stack
restart: unless-stopped
depends_on:
- redis
- postgres
volumes:
- 'stack-blob:/srv/ttn-lorawan/public/blob'
- 'stack-data:/srv/data'
environment:
TTS_DOMAIN: lns.example.com # set this to the IP or domain name of the host you will be using to access the stack
TTN_LW_BLOB_LOCAL_DIRECTORY: /srv/ttn-lorawan/public/blob
TTN_LW_REDIS_ADDRESS: redis:6379
TTN_LW_IS_DATABASE_URI: postgres://root:root@postgres:5432/ttn_lorawan?sslmode=disable
CLI_AUTO_LOGIN: "false"
labels:
io.balena.features.balena-api: '1'

ports:

- "80:1885"
- "443:8885"

- "1881:1881"
- "1882:1882"
- "1883:1883"
- "1884:1884"
- "1885:1885"
- "1887:1887"

- "8881:8881"
- "8882:8882"
- "8883:8883"
- "8884:8884"
- "8885:8885"
- "8887:8887"

- "1700:1700/udp"

--

--

Somsak Lima
Somsak Lima

Written by Somsak Lima

สนับสนุนและส่งเสริมให้ผู้สนใจสามารถใช้งานเทคโนโลยี LoRa และ LoRaWAN ได้ โดยนำความรู้ที่ได้ไปต่อยอดเพื่อใช้งาน

No responses yet