TRX-DOCสำหรับนักพัฒนาอุปกรณ์

มาตรฐานข้อความอุปกรณ์ trix-node/1

สัญญาระหว่าง firmware กับ TRIX: telemetry, status, meta, คำสั่ง, OTA และ provisioning

สัญญาระหว่าง 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

อุปกรณ์ต้องทำครบทุกข้อ ไม่อย่างนั้นห้ามแฟลช

  1. ตรวจลายเซ็นของ token ด้วย public key ที่ฝังใน firmware token ที่ไม่มี exp ถือว่าไม่ผ่าน
  2. ค่าใน payload ที่ลงลายเซ็นต้องตรงกับ type version size sha256 ใน manifest และ type ต้องตรงกับชนิดของตัวเอง
  3. version ต้องใหม่กว่ารุ่นที่รันอยู่ ห้าม downgrade
    • ลำดับรุ่นตาม semver: 1.3.0-rc1 น้อยกว่า 1.3.0
    • ถ้ารุ่นที่รันอยู่อ่านไม่ออก (หน่วยความจำว่าง หรือรุ่นก่อนมาตรฐาน) ให้รับรุ่นใหม่ เพื่อกู้ตัวเองได้
    • นาฬิกาต้อง sync NTP แล้ว และเวลาปัจจุบันต้องไม่เกิน exp ถ้ายังไม่ sync ให้เลื่อนการตรวจไปก่อน
  4. ดาวน์โหลดลง slot สำรอง (A/B) แล้วคำนวณ sha256 ของทั้งไฟล์ให้ตรงก่อนยืนยันการแฟลช
  5. รายงานแต่ละขั้นที่ 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

ติดปัญหาหรือต้องการข้อมูลเพิ่ม ติดต่อทีม TRIX
แชท LINEโทรหาเรา