สร้างปุ่ม LoRaWAN Downlink ด้วย RESTful API บน Grafana ด้วย JavaScript และ BootStrap

ลงไม้ลงมือ : “LoRaWAN dowlink บน Grafana เชื่อมต่อ CAT Network Server”
บทความ โดย… วิสิทธิ์ เวียงนาค
วันที่ 19 กันยายน 2562

บทความนี้เหมาะสำหรับผู้ที่มีพื้นฐานการเขียนโปรแกรมมาบ้าง

ทุกปีพอเริ่มปลายฝนต้นหนาว ก็จะเริ่มเจอข่าวเกี่ยวกับอนุภาคฝุ่นขนาดเล็ก PM2.5/PM10 กันมากขึ้น โหนดวัดคุณภาพอากาศ SaiJai ก็เริ่มได้รับความสนใจขึ้นมาอีกครั้ง มาครั้งนี้โหนด SaiJai ได้พัฒนาขึ้นไปอีกขั้น จากที่สามารถวัดคุณภาพอากาศเพื่อดูแนวโน้มได้เพียงอย่างเดียว ตอนนี้มันยังสามารถควบคุมอุปกรณ์จากระยะทางไกลได้อีกด้วย เช่น สั่งให้เปิดปั๊มน้ำพ่นหมอก เปิดเครื่องฟอกอากาศ และเปิดพัดลมดูดอากาศเป็นต้น การควบคุมระยะทางไกลทำได้โดยการส่ง Downlink แบบ Class-C จาก Network Server ไปยังอุปกรณ์ปลายทาง ในบทความนี้ผู้เขียนจะสาธิตแสดงวิธีการขั้นตอนการสร้างปุ่ม Downlink บน Grafana รวมถึงใช้ Bootstap ปรับแต่งหน้าตาเสริมหล่อให้ดูน่าสนใจมากขึ้นและการเขียนฟังก์ชัน JavaScpit เพื่อเชื่อมต่อกับ Network Server ของ CAT เพื่อส่ง Downlink ด้วย Http RESTful API 😁

SaiJai Sensor Node with PM2.5/10 Sensor

ผู้เขียนเลือกใช้บอร์ด SaiJai dev board แทนที่ SaiJai Sensor Node สำหรับการสาธิตทดสอบในครั้งนี้ ถึงแม้จะเป็นบอร์ดรุ่นเล็กสำหรับการเรียนรู้ แต่ก็มีโมดูล LoRa เช่นเดียวกับบอร์ด SaiJai Sensor Node บอร์ดตระกูล SaiJai จะใช้ ESP32 เป็นหน่วยประมวลผลหลักและมีโมดูล LoRaWAN (AS923) อยู่ในตัว ใช้คลื่นความถี่ 920–925 MHz จากค่าย ACER ซึ่งความพิเศษของโมดูล LoRaWAN นี้อยู่ที่มันได้รับการ “รับรองจากทาง กสทช อย่างถูกต้อง” เรียบร้อยแล้ว และมันยังมี Library เตรียมไว้ให้ จึงทำให้การเขียนโปรแกรมเป็นเรื่องง่ายๆ เลยครับ

รูปแสดงบอร์ด SaiJai dev board

บอร์ด SaiJai dev board ใช้การติดต่อสื่อสารข้อมูลไปยังโมดูล LoRaWAN ด้วย UART แบบ Hardware Serial ผ่าน GPIO พอร์ต 16 และ 17 (RX,TX) ใช้ Library SaiJai.h สำหรับการพัฒนาโค๊ด

รูปแสดง Pin Out ของบอร์ด SaiJai dev board

มารู้จัก LoRa Downlink Class-C กันก่อน

รูปแสดงรายละเอียด Downlink Class-C

ทุกครั้งที่บอร์ดเร่ิมบูตขึ้นมาใหม่และเชื่อมต่อเครือข่าย LoRa สำเร็จแล้ว ท่านจำเป็นต้องสั่งให้บอร์ด “ส่ง Uplink Payload ออกไปให้กับ Network Server (Transmit)” ทราบด้วยว่า ตอนนี้บอร์ดของท่านพร้อมรอรับข้อมูลแล้ว มิเช่นนั้นบอร์ดจะไม่สามารถรับ Downlink Payload ได้ มีหลายท่านเข้าใจผิดไปว่า “หลังจากบอร์ด Joined สำเร็จแล้ว บอร์ดก็สามารถรอรับ payload ได้เลย” จริงๆ แล้วไม่ใช่นะครับ

การใช้งาน Downlink ด้วย Class-C นั้น หลังจากบอร์ดของท่านได้ Joined เข้าเครือข่ายสำเร็จแล้ว ย้ำอีกทีว่า มันต้องส่ง Uplink Payload ออกไปให้กับ Network Server อย่างน้อยหนึ่งครั้ง เพื่อรายงานตัว จากน้ันบอร์ดจะทำการเปิดสล๊อต (RxDelay1) รอไว้ และเปิดสล๊อตยาวๆ (RxDelay2) ทิ้งไว้ ทันทีที่มี Downlink Payload ส่งมาจาก Network Derver มันจะรู้ในทันที การทำงานในลักษณะนี้เหมาะสำหรับงานควบคุมอุปกรณ์ต่างๆ เช่นการปิดเปิด หลอดไฟ ที่สามารถสั่งปิดเปิดแบบเรียลไทน์ได้เลย

การเปิดสล๊อต (RxDelay2) มันจะเปิดรอทิ้งไว้จนกระทั่ง บอร์ดมีการส่ง Uplink Payload (Transmit) ขึ้นไปใหม่ให้ Network Server มันก็จะเร่ิมกระบวนการเปิดสล๊อต RxDelay1 และ RxDelay2 ใหม่อีกครั้ง

สำหรับใครตอนนี้ที่ใช้โมดูล LoRaWAN ของค่ายอื่นๆ อยู่ ในการรอรับ Downlink Payload ของ Class-C ท่านต้องส่ง AT Command (AT+RECVB) เข้าไปถามโมดูล LoRaWAN เพื่อเช็ค Incoming Payload อยู่ตลอดเวลา ว่ามีเข้ามาหรือไม่ ทำให้ MCU หมดสิทธิ์เข้าโหมด Deep Sleep อย่างแน่นอน แต่สำหรับโมดูลของ ACER ที่อยู่บนบอร์ด SaiJai dev board แตกต่างกัน มันไม่ต้องทำแบบน้ันก็ได้ ทันทีที่ได้รับ Downlink Payload ตัวโมดูลมันจะแจ้งและส่ง Payload ออกมาให้เองและส่ง สัญญาณ Interrupt ออกมาด้วย ซึ่งจะช่วยลดการทำงานของ MCU ลง หรือจะออกแบบสั่งให้ MCU เข้าโหมด Deep Sleep แล้วใช้ Interrupt ปลุกให้ตื่นก็ได้ บอร์ด SaiJai dev board มันไม่ต้องคอยลูปส่ง AT Command เพื่อคอยเช็ค Payload เข้ามา ใครที่เคยใช้ Class-C มาก่อน คงจะเคยหงุดหงิดกับประเด็นนี้มาก่อนแน่นอน 😁

อีกหนึ่งฟีเจอร์ดีๆ ของบอร์ดตระกูล SaiJai ที่ใช้ LoRaWAN โมดูลจากค่าย ACER คือการรอ Downlink Payload แบบ Class-C แล้ว MCU ยังสามารถออกแบบให้ลดการทำงานลงได้โดยให้มันเข้าโหมด Deep Sleep นั่นเอง เยี่ยมมากครับ 👍

(1) เตรียมโค๊ดใน SaiJai dev board

ตัวอย่างการรับ Downlink Payload แบบ Class-C ด้วยไลบรารี่ SaiJai การเขียนโค๊ดจะนำความสามารถการทำงานแบบ MultiTask ของ FreeRTOS ที่อยู่ใน ESP32 มาใช้ โดยการสร้างทาสก์ขึ้นมาแล้วตั้งชื่อว่า “Task1” ทำงานคู่ขนานอย่างเป็นอิสระกับทาสก์หลัก หน้าที่ของทาสก์นี้คือ การรอรับ Downlink Payload ทันทีที่มี Payload ส่งเข้ามามันจะคอยเช็คว่าใช่ “0101” หรือไม่ ถ้าไม่ใช่ก็ปล่อยผ่านไป แต่ถ้าใช่ก็จะทำการเปลี่ยนสาถานะ GPIO2 ให้เป็น HIGH ซึ่งจะส่งผลทำให้หลอดไฟ LED บนบอร์ดติดขึ้นมา แล้วหน่วงเวลาไว้ 5 วินาที จากนั้นเปลี่ยนสถานะ GPIO2 ให้เป็น LOW ซึ่งจะส่งผลทำให้หลอดไฟ LED บนบอร์ดดับลง

เขียนโค๊ดสั้นๆ แต่ใช้งานได้จริงนะครับ

#include "SaiJai.h"
SaiJai lora;
void Task1(void *p) { pinMode(2, OUTPUT);
String payload;
while (true) {
payload = lora.payload("C");
Serial.println("===> " + lora.dport + ":" + lora.dpayload);
if (payload == "0101") {
digitalWrite(2, HIGH);
delay(5000);
digitalWrite(2, LOW);
}
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
void setup() { Serial.begin(9600);
Serial2.begin(9600);
xTaskCreate(&Task1, "Task1", 1024, NULL, 10, NULL);
lora.join();
lora.sendb(22, "000000");
}
void loop() {
}

สำหรับการประยุกต์นำไปใช้งานจริง เพื่อควบคุมอุปกรณ์ระยะทางไกล เช่น ควบคุมปั๊มน้ำพ่นหมอก แนะนำว่าท่านควรมีกล่องควบคุมอุปกรณ์ด้วย ยกตัวอย่างตามรูปด้านล่าง กล่องควบคุมปั๊มน้ำพ่นหมอก จะนำขา GPIO21 จากบอร์ด SaiJai Sensor Node ต่อเข้ากับโซลิดสเตตรีเลย์ 10A (Solid State Relay 10A) ซึ่งเป็นสวิทซ์อิเล็กทรอนิกส์ที่ใช้สำหรับการควบคุม เปิดปิดให้กับไฟฟ้ากระแสสลับ 220 VAC รองรับกระแสไฟฟ้าโหลดสูงสุด 10A มันไม่มีส่วนที่เป็นหน้าสัมผัส ท่านจะไม่ได้ยินเสียงขณะทำงาน ไม่ต้องกังวลเรื่องเกิดปัญหาเรื่องฝุ่นเกาะหน้าสัมผัสและมันสามารถทำงานได้เร็วมาก แรงดันที่ใช้ในการควบคุมต่ำเป็นแรงดันไฟฟ้ากระแสตรง 3–32VDC

ถ้าบอร์ด SaiJai Sensor Node เปลี่ยนสถานะ GPIO21 เป็น HIGH มันจะส่งไฟกระแสตรง 3.3VDC ออกไป หลังจากที่โซลิดเตตรีเลย์ ได้รับไฟ 3.3VDC ที่จ่ายเข้ามามันจะทำงานในทันทีโดยการ ปล่อยผ่านไฟกระแสสลับ 220 VAC ที่ต่อไว้ ไปยังแมกเนติกคอนแทคเตอร์ (Magnetic Contactor) ซึ่งจะทำให้เนติกคอนแทคเตอร์ เปิดสวิตซ์ทำงานแบบอัตโนมัตินั่นเอง (เสมือนยก breakerให้ทำงาน) ตอนนี้ปั๊มน้ำพ่นหมอกก็จะมีไฟฟ้ากระแสสลับ 220 VAC จ่ายเข้าไป มันก็จะเริ่มทำงานปั๊มน้ำพ่นหมอกในทันที 💦

แต่หลังจากที่สถานะ GPIO21 เป็น LOW บอร์ดจะหยุดการจ่ายไฟ 3.3VDC ให้กับโซลิดเตตรีเลย์ ซึ่งจะทำให้โซลิดเตตรีเลย์หยุดการทำงาน ทำให้ไม่มีไฟกระแสสลับ 220VAC จ่ายไปให้แมกเนติกคอนแทคเตอร์ (Magnetic Contactor) ปั๊มน้ำพ่นหมอกก็จะหยุดการทำงานลง

รูปแสดง กล่องควบคุมปั๊มน้ำพ่นหมอก

รู้จัก Downlink API ของ CAT network server

ก่อนที่จะเขียนโค๊ดเชื่อมต่อกับ CAT Network Server เพื่อส่ง Downlink Payload มาทำความใจขั้นตอนวิธีการกันก่อน เริ่มต้นท่านต้องขอชุดข้อมูล Token โดยการนำเอา username และ password ที่เป็นตัวเดียวกันที่ใช้ล๊อคอินเข้าระบบ CAT Portal มาขอชุดข้อมูล Token มีรายละเอียดตามข้างล่างนี้

Method: แบบ POST
URL: https://loraiot.cattelecom.com/portal/iotapi/auth/token

curl -X POST
-H 'Content-Type: application/json'
-H 'Accept: application/json'
-d '{
"username" : "xxxxxx",
"password" : "xxxxxx"
}'
https://loraiot.cattelecom.com/portal/iotapi/auth/token
Response{
"access_token" : "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
"expires_in" : 2668"
...
}

มาดูตัวอย่างการขอชุดข้อมูล Token ด้วยโปรแกรม Postman กันครับ หลังจากที่เปิดโปรแกรม Postman และสร้าง New Request แล้ว ให้ไปที่เมนู Headers แล้วเลือก

Mothod เป็น POST ระบุ URL เป็น https://loraiot.cattelecom.com/portal/iotapi/auth/token

เพิ่ม KEY และ VALUE ตามข้างล่างนี้

Content-Type: application/json
Accept: application/json
รูปแสดง การตั้งค่า Headers ในโปรแกรม Postman

ไปที่เมนู Body แล้วเลือก raw สร้างชุดข้อมูลแบบ JSON ประกอบไปด้วย username และ password ซึ่งเป็นตัวเดียวกันกับที่ล๊อคอินเข้าระบบ CAT Portal พอเสร็จเรียบร้อยแล้วให้คลิ๊กที่ปุ่ม Send

รูปแสดง การตั้งค่า Body ในโปรแกรม Postman

โปรแกรม Postman จะเชื่อมต่อกับ CAT Network Server ด้วย Http RESTful API เพื่อร้องขอชุดตัวเลข Token ถ้าสำเร็จ ก็จะแสดงผลลัพธ์ออกมาตามรูปข้างล่าง ประกอบไปด้วย access_token, token_type, refresh_token, expires_in และ scope

รูปแสดง ผลลัพธ์การขอชุดข้อมูล Token ด้วย RESTful API

หลังจากที่ได้รับหมายเลขชุด Token แล้ว ขั้นต่อไปจะทดสอบการส่ง Downlink Payload ด้วย Http RESTful API ไปยัง CAT Network Server ด้วยโปรแกรม Postman เพื่อให้เห็นภาพวิธีการทำงานก่อนลงมือเขียน Script จริง

URL: POST /iotapi/core/devices/{devEui}/downlinkMessages

curl -X POST
-H 'Content-Type: application/json'
-H 'Accept: application/json'
-H 'Authorization: Bearer [access_token]'
-d '{
"payloadHex" : "xxxxxx",
"targetPorts" : "xx"
}'
https://loraiot.cattelecom.com/portal/iotapi/core/devices/{devEui}/downlinkMessages
Response{
"payloadHex" : "xxxxxx",
"targetPorts" : "xx"
"status" : "status_reason"
}

ตัวอย่างการเชื่อมต่อ CAT Network Server ด้วย Http RESTful API เพื่อส่ง Downlink Payload เร่ิมต้นด้วยการกำหนด Header ตามรายละเอียดด้านล่าง ที่ Authorization ให้ระบุ Bearer ในช่อง VALUE แล้วเคาะหนึ่งครั้งตามด้วยหมายเลขชุด Token ที่ได้มาจากขั้นตอนที่ผ่านมา

Content-Type: application/json
Accept: application/json
Authorization: Bearer ********หมายชุด-Token-ที่ได้มา**************
รูปแสดง การตั้งค่า Headers เพื่อส่ง Downlink Payload

ที่เมนู Body กำหนด Payload ในรูปแบบเลขฐาน 16 (HEX) และหมายเลขพอร์ตที่จะส่งไป ในท่ีนี้ Payload คือ “0101” และหมายเลขพอร์ตสำหรับการอ้างอิงคือ 33 จากนั้นให้กดปุ่ม Send

ถ้าการส่ง Downlink Payload สำเร็จ ที่หน้าต่าง Response ท่านจะพบกับข้อความที่ระบบตอบกลับมา ประกอบไปด้วย payloadHEX , targetPorts และ status

รูปแสดง ผลลัพธ์การส่ง Downlink Payload ด้วย RESTful API

ลองเข้าไปดูที่ CAT Network Server ที่เมนู LOGGER ท่านจะพบว่ามีการส่ง Downlink Payload ออกไปหาอุปกรณ์แล้ว จะเห็นว่ามีสัญลักษณ์ลูกศรสีแดงชี้ลง ตามรูปด้านล่างท่านจะพบว่ามีการส่ง Downlink Payload ออกไป 3 ครั้งติดต่อกันโดยใช้พอร์ตหมายเลข 33

มาถึงตอนนี้ท่านคงพอเห็นภาพขั้นตอนการส่ง Downlink Paylaod กันแล้วนะครับ

รูปแสดง หน้า LOGGER ใน CAT Network Server

(2) สร้างปุ่ม Payload Downlink ใน Grafana

หลายท่านคงได้ยินและทดลองใช้โปรแกรม Grafana กันมาบ้าง มันถือว่าเป็นโปรแกรมสร้าง Dashboard ที่ยอดเยี่ยมตัวหนึ่งเลยทีเดียว ที่สำคัญมันเป็น OpenSource ใช้งานได้ฟรีอีกด้วย ผู้เขียนเคยนำเอา Grafana มาจับคู่กับ time series database เช่น Influxdb และ Prometheus ใช้งานจริงๆ มาแล้วหลายโปรเจค เป็นระบบ Monitoring Dashboard ที่ยอดเยี่ยมมากๆ Power FULL มากครับ

การใช้โปรแกรม Grafana เรียนรู้ได้ง่าย มี Widgaet เริ่มต้นดีๆ ให้เลือกใช้อยู่หลายตัว เช่น Guage / Graph / Table และอื่นๆ อีกมากมาย พร้อมทั้งยังสามารถติดตั้ง Widget เพิ่มเติมได้เองอีกด้วย

แต่การใช้ Grafana ส่วนใหญ่ จะเป็นการใช้แบบทางเดียว คือให้ Grafana ดึงข้อมูลจากฐานข้อมูลมาแสดงผล

แล้วถ้าต้องการควบคุมอุปกรณ์ จะทำอย่างไร ?

หลายท่านคงมีข้อสงสัยอยู่ในใจและอาจจะยังไม่ทราบว่า Gafana สามารถสร้างปุ่มเพื่อควบคุมอุปกรณ์ได้ด้วย โดยใช้ JavaScript ผ่านทาง Http RESTful API พร้อมทั้งยังสามารถเรียกใช้ Bootstep มาเสริมหล่อได้อีก ในบทความนี้ผู้เขียนจะไม่ได้ลงรายละเอียดการสร้าง Widget แต่ละตัวเพราะมีรายละเอียดมาก แต่จะสาธิตเฉพาะการสร้างปุ่ม (button) และเขียน JavaScipt เชื่อมต่อ CAT Network Server ส่ง Downlink Paylaod เท่านั้น

เร่ิมต้นการสร้าง Wigdget ปุ่ม Downlink Payload โดยการล๊อคอินเข้าหน้าหลัก Grafana แล้วคลิ๊กที่ Add panel ตรงแถบเมนูด้านบน แล้วเลือก Widget ที่จะทำการสร้าง ในที่นี้ให้ใช้ Mouse คลิ๊กที่ “Text

รูปแสดง หน้าหลักของ Grafana

แก้ไข “Text” โดยการคลิ๊กที่เครื่องหมายสามเหลี่ยมหัวลง ที่ Panel Tile แล้วคลิ๊กที่ “Edit” ในเมนู

รูปแสดง การแก้ไข Widget Text

ที่เมนู Options ใน Widget “Text” ให้เลือก Mode เป็นแบบ html และที่ Content ให้คัดลอกโค๊ดด้านล่างแล้ววางลงไป การตั้งค่าให้ไปที่บริเวณ — config here — เปลี่ยนค่าตัวแปร deveui ของโมดูล LoRa เป็นของท่านเอง แล้วแก้ไข username และ password ให้เป็นตัวเดียวกันกับเข้า CAT Portal ตรงนี้สำคัญอย่าลืมเปลี่ยนนะครับ!

รูปแสดง การตั้งค่าที่จำเป็นในโค๊ด JavaScript

อธิบายการใช้งานของโค๊ดส่ง Downlink Payload ตามนี้ครับ เริ่มจากเลือกเวลาที่ต้องการเปิดการทำงานของอุปกรณ์ปลายทาง มีให้เลือกตั้งแต่ 01–05, 10, 15, 20 นาที จากนั้นให้คลิ๊กที่ปุ่ม “OFF” สีแดง โปรแกรมจะแสดง pop-up ขึ้นมาพร้อมกับข้อความ “Please confirm to downlink agian” ให้ยืนยันการทำงานด้วยคลิ๊กที่ปุ่ม “Ok” จากนั้นโปรแกรมจะใช้ ajax เชื่อมต่อกับ CAT network sever ด้วย Http RESTful API เพื่อขอชุดข้อมูล Token แล้วส่ง Downlink ในระหว่างนี้ข้อความในปุ่มจะแสดง “Downlink…” ขึ้นมา ถ้าสำเร็จแล้ว ปุ่มจะเปลี่ยนเป็นสีเขียวและแสดงข้อความ “ON” พร้อมแสดงเวลานับถอยหลังจนครบเวลาที่เลือกไว้ หลังจากที่หมดเวลาข้อความเวลานับถอยหลังจะหายไป และปุ่มจะเปลี่ยนสีเป็นสีแดงพร้อมแสดงข้อความ “OFF” อีกครั้ง เป็นอันสิ้นสุดการทำงานของโปรแกรม 😁

<script>
/* LoRaWAN payload downlink for CAT network server */
/* Script by Visit Wiangnak */
/* https://web.facebook.com/visit.wiangnak */
/* 19 May 2019 */
/* --------------- config here --------------- */ var deveui = "000111222333";
var username = "xxxxxxxxx";
var password = "11112222333";
var port_on = "15";
var port_off = "16";
var label_on = "ON";
var label_off = "OFF";
/* --------------- config here --------------- */function get_token(payload, port, delaytime) {
var dtxt = JSON.stringify({
"username": username,
"password": password
});
$.ajax({
type: "POST",
url: "https://loraiot.cattelecom.com/portal/iotapi/auth/token",
data: dtxt,
contentType: "application/json",
crossDomain: true,
dataType: "json",
success: function (data, status, jqXHR) {
var token = data[
"access_token"
];
downlink(token, payload, port, delaytime);
},
error: function (jqXHR, status) {
console.log(jqXHR);
alert('fail' + status.code);
}
});
}
function downlink(token, payload, port, delaytime) {
var dtxt = JSON.stringify({
"payloadHex": payload,
"targetPorts": port
});
var url = "https://loraiot.cattelecom.com/portal/iotapi/core/devices/" + deveui + "/downlinkMessages";
$.ajax({
type: "POST",
url: url,
data: dtxt,
contentType: "application/json",
headers: {
Authorization: "Bearer " + token
},
crossDomain: true,
dataType: "json",
success: function (data, status, jqXHR) {
document.getElementById("lamp1").innerHTML = "<i class=\"fa fa-toggle-on\"></i> " + label_on;
document.getElementById("lamp1").value = 1;
document.getElementById("lamp1").className = "btn btn-success";
countdown(delaytime / 60000);
setTimeout(function () {
document.getElementById("lamp1").innerHTML = "<i class=\"fa fa-toggle-off\"></i> " + label_off;
document.getElementById("lamp1").value = 0;
document.getElementById("lamp1").className = "btn btn-danger";
document.getElementById("mycountdown").innerHTML = "";
}, delaytime);
},
error: function (jqXHR, status) {
console.log(jqXHR);
alert('fail' + status.code);
}
});
}
function btnconfirm() {
var selecttime = document.getElementById("sel1").value;
var payload_on = "01" + selecttime;
var delaytime = selecttime * 60000;
var status = document.getElementById("lamp1").value;
var r = confirm("Press confirm to downlink again.");
if (r == true) {
if (status == 0) {
get_token(payload_on, port_on, delaytime);
document.getElementById("lamp1").innerHTML = "Downlink...";
}
}
}
function countdown(minutes) {
var seconds = 60;
var mins = minutes
function tick() {
var counter = document.getElementById("mycountdown");
var current_minutes = mins - 1
seconds--;
counter.innerHTML = current_minutes.toString() + ":" + (seconds < 10 ? "0" : "") + String(seconds);
if (seconds > 0) {
setTimeout(tick,
1000);
} else {
if (mins > 1) {
countdown(mins - 1);
}
}
}
tick();
}
</script><div class="form-group">
<label for="sel1">Select Time (Minute):</label>
<select class="form-control" style="font-size:15px;height:30px;width:100%" id="sel1">
<option>01</option>
<option>02</option>
<option>03</option>
<option>04</option>
<option>05</option>
<option>10</option>
<option>15</option>
<option>20</option>
</select>
</div>
<div>
<h4>
<p id="mycountdown"></p>
<h4>
<button style="font-size:30px;height:60px;width:100%" id="lamp1" value=0 type="button"
class="btn btn-danger" onclick="btnconfirm()"><i class="fa fa-toggle-off"></i> OFF</button>
</div>

ไปที่เมนู General เพื่อตั้งชื่อ Title ที่นี้ตั้งชื่อว่า “Downlink Button” แล้วคลิ๊กเครื่องหมายลูกศรสีฟ้า หัวมุมขวาด้านบนเพื่อกลับมายังหน้าหลัก

รูปแสดง การตั้งชื่อให้ Title ของปุ่ม button

ปรับขนาดและตำแหน่งของปุ่มให้เรียบร้อยสวยงาม เป็นอันเสร็จขั้นตอนการสร้างปุ่ม Downlink Payload ครับ แล้วอย่าลืม SAVE กันนะครับ 👍

รูปแสดง หน้า dashboard และปุ่ม Downlink Payload บน Grafana

มาดูการทดลองส่ง Downlink Payload ของจริงกัน บน Grafana ตาม Video Clip ข้างล่างนี้ครับ

การที่ Grafana รองรับการเขียน JavaScript มันลบข้อจำกัดเดิมๆ ลงไปได้มาก Power FULL จริงๆ ความสามารถนี้เป็นสิ่งที่ผู้เขียนชอบมากๆ เพราะสามารถนำไปประยุกต์ใช้งานได้อย่างหลากหลาย ท่านสามารถใช้ ajax ไปดึงเอารูปภาพ หรือ VDO จากแหล่งต่างๆ มาแสดงบนหน้า Grafana ได้ หรือจะสั่งให้ Grafana ควบคุมอุปกรณ์ต่างๆ ผ่าน API ก็ทำได้เช่นเดียวกัน

ผู้เขียนมีความตั้งใจที่จะนำเสนอการใช้ IoT-LoRaWAN-NBIOT สำหรับพัฒนา SMART CITY เพื่อให้ผู้ที่สนใจนำไปพัฒนาต่อยอดสร้างนวกรรมใหม่ๆ ขอเป็นส่วนหนึ่งเล็กๆ น้อยๆ ช่วยผลักดันประเทศของเราให้เข้าสู่ยุคดิจิตอล Thailand 4.0 อย่างแท้จริง

ติดตามข่าวสารทาง facebook ได้ที่ลิงค์นี้

--

--