สัญญาระหว่าง firmware ของอุปกรณ์ IoT กับ TRIX Monitor สำหรับนักพัฒนาที่เขียน firmware เอง ถ้าแค่ต้องการต่ออุปกรณ์ทดสอบ เริ่มที่ ต่ออุปกรณ์เข้า TRIX Monitor ก่อน
1. Topic
trix/<site>/<device-id>/<channel>
site= ชื่อย่อของ site ใน TRIX ส่วนdevice-id= รหัสอุปกรณ์ภายใน site นั้น- อุปกรณ์ใหม่ใช้ตัวพิมพ์เล็ก ตัวเลข และ
-ยาวไม่เกิน 48 ตัว เช่นbme-005,inv-01- ระบบยอมรับ
A-Z a-z 0-9 _ . -ยาวไม่เกิน 64 เพื่อให้อุปกรณ์รุ่นเก่ายังใช้ได้ - topic ที่ไม่ผ่านเกณฑ์นี้ หรือชื่อค่าผิดรูปแบบ จะถูกทิ้ง
- ระบบยอมรับ
- MQTT client id =
<site>/<device-id>เพราะ device-id ซ้ำข้าม site ได้ - ไม่ขึ้นต้น topic ด้วย
/และไม่ใส่ช่องว่าง - login ของ site ส่งได้เฉพาะ
trix/<site>/#ส่วน login ของอุปกรณ์ส่งได้เฉพาะtrix/<site>/<device-id>/#
| channel | ทิศทาง | retain | payload |
|---|---|---|---|
telemetry |
อุปกรณ์ไป server | no | JSON ค่าที่วัดได้ 1 รอบ |
status |
อุปกรณ์ไป server | yes | {"online":true,...} ตอนเชื่อมต่อ และ LWT {"online":false} |
meta |
อุปกรณ์ไป server | yes | อุปกรณ์คืออะไร ส่งครั้งเดียวหลังเชื่อมต่อ |
cmd |
server ไปอุปกรณ์ | no | คำสั่ง |
ack |
อุปกรณ์ไป server | no | ผลของคำสั่ง |
ota |
อุปกรณ์ไป server | no | ความคืบหน้าและผลของ OTA |
- QoS: LWT ตั้งเป็น QoS 1 ข้อความอื่นส่งที่ QoS 0 ได้ ฝั่ง server subscribe ที่ QoS 1
- ข้อความ retained: broker ส่ง retained ซ้ำทุกครั้งที่มีการ subscribe ใหม่ ระบบจึงจัดการดังนี้
status/metaที่เป็น retained: บันทึกสถานะ แต่ไม่นับเป็นเวลาที่เห็นอุปกรณ์ล่าสุดtelemetryที่เป็น retained: ทิ้ง ไม่บันทึกเป็นค่าใหม่ อย่าตั้ง retain ให้ telemetry
- ลำดับข้อความ:
status/meta/ota/ackของอุปกรณ์เดียวกันถูกประมวลผลตามลำดับที่มาถึง - จำกัดการสร้างอัตโนมัติ: อุปกรณ์และค่าใหม่สร้างได้ไม่เกิน 200 รายการต่อชั่วโมง กันชื่อขยะท่วมระบบ
topic แบบเดิม trix/<site>/<device-id>/<metric> ที่ payload เป็นตัวเลขเปล่ายังรับอยู่
เพื่อให้อุปกรณ์ที่แฟลชก่อน v1 ทำงานต่อได้ แต่อุปกรณ์ใหม่ห้ามใช้
ชื่อค่าจึงห้ามซ้ำกับชื่อ channel ทั้ง 6 ตัว (state ยังใช้เป็นชื่อค่าได้)
2. telemetry
{"ts":1760600000,"seq":12,"temperature_c":25.3,"humidity_pct":61.2,"relay_on":true}
- 1 ข้อความต่อ 1 รอบการวัด ไม่เกิน 64 ค่า
ts= unix seconds (UTC) ของเวลาที่วัด ไม่ใส่ก็ได้ถ้านาฬิกาอุปกรณ์ยังไม่ sync- ถ้าย้อนหลังเกิน 7 วัน หรือล่วงหน้าเกิน 5 นาทีจากเวลา server ระบบใช้เวลาของ server แทน
seq= ตัวนับเพิ่มทีละ 1 หลังบูต ใช้ดูว่าข้อความหายv,fwสงวนไว้ ไม่ถูกบันทึกเป็นค่าvia= id ของ gateway ที่ส่งต่อข้อมูลของ node LoRa แทน- ต้องผ่านกฎเดียวกับ device-id ไม่อย่างนั้นจะถูกปฏิเสธ
- ไม่ถูกบันทึกเป็นค่า ระบบจำไว้ว่าข้อมูลล่าสุดมาทาง gateway ไหน
- ส่ง
rssi_dbmและsnr_dbของลิงก์ LoRa เป็นค่าปกติคู่กัน
- ค่าที่บันทึกต้องเป็นตัวเลข boolean แปลงเป็น 1/0 ข้อความและ object ถูกปฏิเสธ
- ชื่อ key เป็น snake_case ตัวพิมพ์เล็ก ลงท้ายด้วยหน่วย ระบบเติมหน่วยให้ค่าใหม่จากท้ายชื่อ
| ท้ายชื่อ | หน่วย | ตัวอย่าง |
|---|---|---|
_c |
C | temperature_c |
_pct |
% | humidity_pct, battery_soc_pct |
_hpa _kpa |
hPa kPa | pressure_hpa |
_v _a _w _kw |
V A W kW | voltage_v, current_a, power_w |
_wh _kwh |
Wh kWh | energy_kwh |
_va _var |
VA var | apparent_va |
_hz |
Hz | grid_freq_hz |
_dbm |
dBm | rssi_dbm |
_ppm |
ppm | co2_ppm |
_lux |
lx | light_lux |
_umol |
umol/m2/s | ppfd_umol |
_lpm _l |
L/min L | flow_lpm |
_mm _m |
mm m | rain_mm, level_m |
_s _ms |
s ms | uptime_s |
_deg |
deg | wind_dir_deg |
ค่าที่ไม่มีหน่วย (สถานะ จำนวนนับ) ไม่ต้องมีท้ายชื่อ เช่น relay_on, state, error_count
3. status (birth และ LWT)
ตอนเชื่อมต่อ broker ให้ตั้ง LWT เป็น {"online":false} (QoS 1, retain)
ทันทีที่เชื่อมต่อได้ ส่งข้อความนี้ทับ
{"online":true,"fw":"1.2.0","ip":"192.168.1.20","rssi_dbm":-61,"reset_reason":"poweron","uptime_s":3}
ระบบเก็บ online และรุ่น firmware (fw) ไว้กับอุปกรณ์ ค่าอื่นเก็บเป็นข้อมูลสถานะล่าสุด
ข้อความ online หรือ offline แบบข้อความเปล่าของอุปกรณ์รุ่นเก่ายังรับอยู่
4. meta
{"type":"bme280-node","hw":"esp32dev","fw":"1.2.0","interval_s":60,"sensors":["bme280"]}
type= ชนิดอุปกรณ์ ใช้รูปแบบเดียวกับ device-id และต้องตรงกับชนิดของ firmware ที่ลงทะเบียนไว้ใน TRIX เพราะ OTA เลือกไฟล์ตามค่านี้- ระบบตั้งชนิดอุปกรณ์จาก
typeเฉพาะเมื่อยังเป็นค่าที่สร้างอัตโนมัติ ชนิดที่ทีม TRIX ตั้งเองจะไม่ถูกเขียนทับ
5. cmd และ ack
cmd: {"id":"c-17","action":"reboot"}
cmd: {"id":"c-18","action":"ota_check"}
cmd: {"id":"c-19","action":"set","interval_s":30}
ack: {"id":"c-17","ok":true}
ack: {"id":"c-19","ok":false,"error":"interval_s out of range"}
action มาตรฐาน: reboot, factory_reset (ล้าง WiFi/broker แล้วกลับเป็น setup AP), ota_check, ping และ set สำหรับ interval_s
action อื่นให้โค้ดของแต่ละอุปกรณ์จัดการเอง อุปกรณ์ต้องตอบ ack ทุกคำสั่งที่มี id
6. OTA
GET https://trix.technology/api/ota/check?type=<type>&fw=<semver>&id=<device-id>
| คำตอบ | ความหมาย |
|---|---|
{"ok":true,"upToDate":true,"version":"1.3.0"} |
ไม่ต้องอัปเดต |
{"ok":true,"upToDate":false,"type","version","size","sha256","url","token"} |
มีรุ่นใหม่ |
| 503 | server ยังไม่พร้อมลงลายเซ็น ห้ามอัปเดต |
token = base64url(payload).base64url(sig) โดยที่ payload คือ
{"type","version","size","sha256","exp"} เรียงตามนี้ และ sig คือลายเซ็น Ed25519 ของ payload
exp = unix seconds หมดอายุ 24 ชั่วโมงหลังออก กัน manifest เก่าถูกนำมาเล่นซ้ำ
public key สำหรับตรวจลายเซ็นขอได้จากทีม TRIX แล้วฝังไว้ใน firmware
อุปกรณ์ต้องทำครบทุกข้อ ไม่อย่างนั้นห้ามแฟลช
- ตรวจลายเซ็นของ token ด้วย public key ที่ฝังใน firmware token ที่ไม่มี
expถือว่าไม่ผ่าน - ค่าใน payload ที่ลงลายเซ็นต้องตรงกับ
typeversionsizesha256ใน manifest และtypeต้องตรงกับชนิดของตัวเอง versionต้องใหม่กว่ารุ่นที่รันอยู่ ห้าม downgrade- ลำดับรุ่นตาม semver:
1.3.0-rc1น้อยกว่า1.3.0 - ถ้ารุ่นที่รันอยู่อ่านไม่ออก (หน่วยความจำว่าง หรือรุ่นก่อนมาตรฐาน) ให้รับรุ่นใหม่ เพื่อกู้ตัวเองได้
- นาฬิกาต้อง sync NTP แล้ว และเวลาปัจจุบันต้องไม่เกิน
expถ้ายังไม่ sync ให้เลื่อนการตรวจไปก่อน
- ลำดับรุ่นตาม semver:
- ดาวน์โหลดลง slot สำรอง (A/B) แล้วคำนวณ sha256 ของทั้งไฟล์ให้ตรงก่อนยืนยันการแฟลช
- รายงานแต่ละขั้นที่ channel
ota:checking,downloading,verifying,success,failed,rejected,up_to_date- ตัวอย่าง
{"state":"failed","version":"1.3.0","reason":"sha256"} - หลังรีบูตเข้ารุ่นใหม่ ให้ส่ง
successพร้อมversionระบบจะอัปเดตรุ่น firmware ของอุปกรณ์ให้
- ตัวอย่าง
ช่วงเวลาตรวจ: หลังบูตแบบสุ่มหน่วง 0-2 นาที, ทุก 6 ชั่วโมง (สุ่มเลื่อน 0-30 นาที) และเมื่อได้ cmd ota_check
server จำกัด 120 ครั้งต่อนาทีต่อ IP ใน URL ให้เข้ารหัส + ของ build metadata เป็น %2B
ระหว่างดาวน์โหลดให้รักษาการเชื่อมต่อ MQTT ไว้ (เรียก loop ของ client อย่างน้อยทุกวินาที) เพื่อไม่ให้ LWT ทำงาน
7. Provisioning
GET https://trix.technology/api/portal/<รหัส>/config.json (QR บนหน้า portal ของ site) ให้ค่าต่อไปนี้
- broker, login MQTT และ prefix ของ topic
protocol("trix-node/1"),topic.channelsและota.checkUrl
อุปกรณ์เก็บค่าทั้งหมดลงหน่วยความจำถาวร (เช่น NVS ของ ESP32) ห้ามฝัง login ไว้ใน source code
8. อุปกรณ์ LoRaWAN
node LoRaWAN ไม่ได้พูด MQTT ตรง ส่งผ่าน network server แทน ดู อุปกรณ์ LoRaWAN ผ่าน ChirpStack หรือ TTN
