
ผู้ติดตามบล็อกนี้คงทราบดีแล้วว่า NETPIE คือชื่อของบริการคลาวด์สำหรับอุปกรณ์ไอโอทีที่พัฒนาโดยศูนย์อิเล็กทรอนิกส์และคอมพิวเตอร์แห่งชาติ (NECTEC) และปัจจุบันตั้งบริษัท NEXPIE เพื่อสนับสนุนการใช้ในงานอุตสาหกรรมและเชิงพานิชย์ เมื่อวันที่ 20/02/2020 ที่ผ่านมา ได้เปิดตัวแพลตฟอร์มใหม่ในชื่อ NETPIE 2020 ที่แก้ไขข้อจำกัดของเวอร์ชันก่อน (อ้างถึงโดยชื่อ NETPIE 2015) หลายประการ เช่นยกเลิกการใช้ไลบรารี Microgear ที่ยึดติดกับภาษาและฮาร์แวร์ทำให้ขาดความยืดหยุ่น ปรับปรุงให้รองรับโดยฮาร์ดแวร์และภาษาการโปรแกรมหลากหลายมากขึ้น อย่างไรก็ตามการเปลี่ยนแปลงโครงสร้างของ NETPIE 2020 จากเดิมทำให้โปรแกรมเดิมที่ใช้งานอยู่ไม่สามารถใช้ได้และต้องมีการแก้ไข บทความนี้เป็นแนวทางสำหรับผู้พัฒนาบน NETPIE 2015 ที่ต้องการเปลี่ยนผ่านสู่ NETPIE 2020 โดยตั้งสมมุติฐานว่าผู้อ่านมีประสบการณ์หรือความเข้าใจโปรแกรมและการทำงานของเวอร์ชันเก่าอยู่ก่อนแล้ว สำหรับท่านที่ไม่เคยใช้งาน NETPIE มาก่อนเลยแนะนำให้เริ่มต้นจากคู่มือการใช้งานที่ลิงก์ NETPIE 2020 Documentation
หมายเหตุ : ฮาร์ดแวร์ที่ใช้ในบทความนี้คือบอร์ด ESP8266 หรือ ESP32 แบบทั่วไป (เช่น NodeMCU, NodeMCU-32S, ESP32 Dev kit V1) ที่โปรแกรมโดย Arduino IDE เท่านั้น ไม่รวม M5stack, Raspberry Pi หรือฮาร์ดแวร์อื่น ทั้งนี้การที่ NETPIE 2020 ไม่ขึ้นกับไลบรารี Microgear ทำให้โปรแกรมสำหรับ ESP8266 และ ESP32 ไม่แตกต่างกันในมุมของการเชื่อมต่อกับแพลตฟอร์ม เพื่อความง่ายต่อไปจะอ้างอิงอุปกรณ์ฮาร์ดแวร์ว่า NodeMCU
ก่อนอื่นลองมาทบทวนการพัฒนาบนเน็ตพายเวอร์ชันเก่ากันซะหน่อย ขั้นตอนสำคัญในการตั้งค่าและโปรแกรมเพื่อเชื่อมต่ออุปกรณ์ไอโอทีเข้ากับแพลตฟอร์ม NETPIE 2015 มีดังนี้
ด้าน NETPIE 2015
- ในบัญชีของผู้ใช้ สร้าง Application เป็นเหมือนศูนย์รวมของอุปกรณ์ทั้งหมดที่จะมาต่อในเครือข่ายเดียวกัน ข้อมูลที่ใช้ติดต่อคือชื่อของ Application เรียกว่า APPID
- สร้าง key สำหรับอุปกรณ์ที่ต่อกับ Application โดยเลือกชนิด device key สำหรับอุปกรณ์ฮาร์ดแวร์ (NodeMCU) และ session key สำหรับอุปกรณ์เชิงลอจิก (เบราเซอร์ Freeboard) ข้อมูลที่ใช้ติดต่อคือ KEY และ SECRET เป็นสตริงอักขระที่สร้างโดยเน็ตพาย อุปกรณ์หลายตัวสามารถใช้ KEY และ SECRET ร่วมกันได้
- สร้าง session key สำหรับ Freeboard และนำข้อมูล KEY และ SECRET ไปสร้าง datasource
- ถ้ามีการใช้ FEED สร้าง FEED ในบัญชีผู้ใช้และนำข้อมูล FEEDID, FEEDAPI ไปใช้ด้านอุปกรณ์
ด้าน NodeMCU
(ละเว้นไม่กล่าวถึงส่วนพื้นฐานเช่นการกำหนดขาอินพุต/เอาต์พุต การตั้งค่าพอร์ตอนุกรม ฯลฯ)
บริเวณส่วนหัวของโปรแกรม
- เรียกไลบรารี WiFi, Microgear และไลบรารีอื่นสำหรับเซนเซอร์ เช่น DHT
- กำหนดข้อมูล SSID และ password ของ WiFi router ที่ใช้เชื่อมต่ออินเทอร์เน็ต
- นำข้อมูล APPID, KEY, SECRET จากปัญชี NETPIE มานิยามหรือสร้างเป็นตัวแปรที่ส่วนบนของโปรแกรม
- ตั้งชื่อ ALIAS ให้กับอุปกรณ์ เพื่อใช้อ้างถึงในคำสั่งการสื่อสาร
- นิยามชื่อ topic สำหรับพับลิชข้อมูลที่จะรวมกับชื่อ APPID และ ALIAS
- ถ้าใช้ NETPIE FEED นิยามค่า FEEDID, FEEDAPI
- สร้าง instance ของออปเจ็ค WiFiClient, Microgear และเซนเซอร์ที่ใช้งาน เช่น DHT
- นิยามฟังก์ชันต่างๆ ของไลบรารี Microgear เช่น onMsghandler(), onConnected
ในฟังก์ชัน setup()
- ตั้งค่าเริ่มต้นให้กับเซนเซอร์
- ตั้งค่าเริ่มต้นให้กับฟังก์ชัน Microgear
- เชื่อมต่อ WiFi
ในฟังก์ชัน loop()
- ตรวจสอบการเชื่อมต่อ โดย microgear.connected()
- ถ้ายังเชื่อมต่ออยู่
- คงการเชื่อมต่อไว้ โดยเรียก microgear.loop()
- กำหนดคาบเวลาการอ่านค่าจากเซนเซอร์และพับลิชข้อมูล
- อ่านค่าจากเซนเซอร์
- นำค่าจากเซนเซอร์มาสร้างเป็นสตริง ตามรูปแบบที่คั่นด้วยเครื่องหมาย , ระหว่างค่าแต่ละตัว
- พับลิชข้อมูล ตามชื่อหัวข้อที่ตั้งไว้โดยคำสั่ง microgear.publish()
- หากมีการใช้ FEED สร้างสตริงสำหรับส่งให้ FEED ตามรูปแบบที่ตั้งไว้ และเขียนไปยัง FEED ตามคาบเวลาที่กำหนดโดยคำสั่ง microgear.writeFeed()
- ถ้าการเชื่อมต่อหลุด
- ทำการเชื่อมต่อใหม่ โดย microgear.connect(APPID)
*** สีเหลืองคือส่วนที่ขึ้นกับ NETPIE 2015 และต้องตัดออกหรือแก้ไข ***
Listing 1 ด้านล่างคือตัวอย่างโปรแกรม NodeMCU dhtled_NETPIE15.ino ที่อ่านค่าจากเซนเซอร์ DHT และพับลิชไปยัง NETPIE 2015 ทุก 2 วินาที พร้อมกับเขียนข้อมูลลง FEED ทุก 15 วินาที ในขณะเดียวกันรอรับข้อมูลจากด้านเน็ตพาย หากได้รับข้อมูล 0/1 ก็จะสั่งให้ LED ดับ/ติด เราจะแก้โปรแกรมนี้ให้ทำงานบนแพลตฟอร์ม NETPIE 2020 โค้ดส่วนที่เป็นเหลืองคือคำสั่งที่ใช้กับ NETPIE 2015 และต้องมีการตัดออกหรือแก้ไขเมื่อเปลี่ยนเป็น NETPIE 2020
// dhtled_NETPIE15.ino // dew.ninja Feb 2020 // connect to NETPIE 2015 // and display temperature, humidity // also turn on-board OFF/ON #include <ESP8266WiFi.h> // For ESP32, use #include <WiFi.h> #include <MicroGear.h> // NETPIE 2015 uses Microgear library #include "DHT.h" // library for DHT sensor // ----- WiFi configuration -------------- const char* ssid = "mywifissid"; const char* password = "mywifipwd"; // ******** NETPIE 2015 configuration ********** #define APPID "dnjcommonApp" #define KEY "Ez9K7jzBXx7fzzh" #define SECRET "NLGaQYxDV3ukviUkjJFrcQcPVbZiyf" // ----------- name of this device -------------------- #define ALIAS "dewIoT" // ----- NETPIE 2015 FEED configuration ----- #define FEEDID "dewGHFeed" #define FEEDAPI "YDAq7tDWmFhLh891qqPjOgVF1eWdl0" // ------ topic to publish ----------------------- #define DHTDATATOPIC "/dhtlight/" ALIAS // ************************************************** #define DHTPIN D1 #define DHTTYPE DHT11 // e.g. DHT11, DHT21, DHT22 DHT dht(DHTPIN, DHTTYPE); #define LED1 LED_BUILTIN // use on-board LED float humidity = 0; float temperature = 0; unsigned long lastDHTRead = 0, newDHTRead=0; unsigned long lastTimeWriteFeed = 0, newTimeWriteFeed = 0; WiFiClient client; // ***** NETPIE 2015 Microgear instance and function declarations ****** MicroGear microgear(client); void onMsghandler(char *topic, uint8_t* msg, unsigned int msglen) { Serial.print("Incoming message --> "); msg[msglen] = '\0'; Serial.println((char *)msg); if (*(char *)msg == '0') digitalWrite(LED1,0); else if (*(char *)msg == '1') digitalWrite(LED1,1); } void onConnected(char *attribute, uint8_t* msg, unsigned int msglen) { Serial.println("Connected to NETPIE..."); microgear.setAlias(ALIAS); } // ************************************************************** void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); dht.begin(); // initialize DHT module if (WiFi.begin(ssid, password)) { while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } } Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); // ************** Microgear initialization **************** microgear.on(MESSAGE,onMsghandler); microgear.on(CONNECTED,onConnected); microgear.init(KEY,SECRET,ALIAS); microgear.connect(APPID); // *************************************************** } void loop() { if (microgear.connected()) { microgear.loop(); newDHTRead = millis(); if(newDHTRead - lastDHTRead > 2000) { humidity = dht.readHumidity(); // read humidity temperature = dht.readTemperature(); // read temperature lastDHTRead = newDHTRead; // check if data is valid if (isnan(humidity) || isnan(temperature)) { humidity=0; temperature=0; Serial.println("Failed to read from DHT sensor!"); } else{ String datastring = (String)humidity+","+(String)temperature; Serial.print("Sending --> "); Serial.println(datastring); microgear.publish(DHTDATATOPIC,datastring); } } // ******** NETPIE 2015 FEED write **************** newTimeWriteFeed = millis(); if(newTimeWriteFeed-lastTimeWriteFeed > 15000){ lastTimeWriteFeed = newTimeWriteFeed; if(humidity!=0 && temperature!=0){ String feeddata = "{\"humid\":"; feeddata += humidity ; feeddata += ", \"temp\":"; feeddata += temperature; feeddata += "}"; Serial.print("Write Feed --> "); Serial.println(feeddata); //microgear.writeFeed(FEEDID,feeddata); microgear.writeFeed(FEEDID,feeddata,FEEDAPI); } } // ************************************************ } else { Serial.println("connection lost, reconnect..."); microgear.connect(APPID); } delay(100); }
Listing 1 dhtled_NETPIE15.ino โปรแกรม NodeMCU ที่ใช้เชื่อมต่อกับ NETPIE 2015
การเปลี่ยนแปลงจะอาศัยแนวทางตามตัวอย่างในลิงก์ของ NETPIE https://netpie.io/tutorials/NodeMCU สามารถสรุปได้ดังนี้
- เลิกใช้ไลบรารี Microgear.h เปลี่ยนเป็นไลบรารี PubSubClient.h
- เลิกใช้ข้อมูล APPID, KEY, SECRET เปลี่ยนเป็นข้อมูล Client ID, Token (Username), Secret จาก NETPIE 2020
- มีส่วนที่เพิ่มมาคือชื่อ MQTT server (broker.netpie.io) และพอร์ต (1883)
- ไม่ต้องตั้งชื่อ ALIAS ให้กับอุปกรณ์
- เนื่องจากไม่มีการสร้าง instance ของออปเจ็ค Microgear แล้ว ดังนั้นฟังก์ชันที่เกี่ยวข้องจะลบทิ้งทั้งหมด เปลี่ยนเป็นการเชื่อมต่อในรูปแบบใหม่ที่จะกล่าวถึงต่อไป
- NETPIE 2020 ไม่มี FEED แต่จะยังสนับสนุนการเขียนข้อมูลฐานเวลาที่กำหนดโดย Device Schema
- การตั้งค่าเซนเซอร์และเชื่อมต่อ WiFi ยังคงใช้คำสั่งเดิม
- การอ่านค่าจากเซนเซอร์ยังคงใช้คำสั่งเดิม
ต่อไปจะอธิบายขั้นตอนในการตั้งค่าและโปรแกรมเพื่อเชื่อมต่อ NodeMCU เข้ากับแพลตฟอร์ม NETPIE 2020
ด้าน NETPIE 2020
- Login เข้าสู่หน้า portal
- สร้าง project ใหม่
- บนแท็บ Device List สร้าง device สำหรับ NodeMCU จะเห็นว่า NETPIE 2020 สร้างข้อมูล Client ID, Token, Secret ให้เพื่อที่เราจะนำมาใช้ในโปรแกรม
ก่อนที่จะสร้าง Freeboard ควรตรวจสอบจากด้านล่างของ device ในหน้าต่าง [Shadow] ว่าข้อมูลถูกส่งมาถูกต้องหรือไม่
ด้าน NodeMCU
เราจะแก้ไขโปรแกรม dthled_NETPIE15.ino โดยเซฟไฟล์เป็นชื่อ dhtled_NETPIE20.ino และแก้ไขจากด้านบนลงมา โดยจะใช้อักขระ ---xxx--- ใส่เพิ่มในส่วนหน้าของที่คอมเมนต์ออกด้วย
หมายเหตุ : ที่แนะนำให้ใช้การคอมเม้นต์แทนการลบโค้ดออกโดยถาวร เพราะผู้เริ่มต้นอาจจะพลาดลบเอาโค้ดส่วนที่จำเป็นต้องใช้ออกไป ซึ่งสามารถจะนำกลับคืนมาได้หากพบว่าโปรแกรมทำงานไม่ถูกต้องโดยปลดคอมเม้นต์ บนเมนู Edit ของ Arduino IDE มีตัวเลือก Comment/Uncomment ที่ทำงานในลักษณะสลับสถานะ
เริ่มจากการเรียกไลบรารี คอมเม้นต์ Microgear.h ออก
// ---xxx--- #include <MicroGear.h> // NETPIE 2015 uses Microgear library
และใส่ PubSubClient.h เข้าไปแทน
#include "PubSubClient.h" // library for NETPIE 2020 communication
ส่วนการนิยาม WiFi คงไว้เหมือนเดิม ต่อมาคอมเม้นต์ส่วนตั้งค่าสำหรับ NETPIE 2015 ออกไปทั้งหมด
//// ******** NETPIE 2015 configuration **********
//---xxx--- #define APPID "dnjcommonApp"
//---xxx---#define KEY "Ez9K7jzBXx7fzzh"
//---xxx---#define SECRET "NLGaQYxDV3ukviUkjJFrcQcPVbZiyf"
//
//// ----------- name of this device --------------------
//---xxx---#define ALIAS "dewIoT"
//
//// ----- NETPIE 2015 FEED configuration -----
//---xxx---#define FEEDID "dewGHFeed"
//---xxx---#define FEEDAPI "YDAq7tDWmFhLh891qqPjOgVF1eWdl0"
//
//// ------ topic to publish -----------------------
//---xxx---#define DHTDATATOPIC "/dhtlight/" ALIAS
//// **************************************************
และใส่การตั้งค่าสำหรับ NETPIE 2020 เข้าไปแทน
// ^^^^^^^^^^^^^^ NETPIE 2020 configuration ^^^^^^^^^^^^^^^^^^
const char* mqtt_server = "broker.netpie.io";
const int mqtt_port = 1883;
const char* mqtt_Client = "772e64d-0458-4849-9086-756db53bc2";
const char* mqtt_username = "w16i6Fz4SGtiYqfL2UkxBK9BGWsC4";
const char* mqtt_password = "@OS&ve76I1^S%$45UR!6C~bx~e3k#";
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ลบคำสั่ง
WiFiClient client;
ออก เปลี่ยนเป็นสร้าง instance ของ WiFiClient และ PubSubClient ตามคำสั่งดังนี้
WiFiClient espClient;
PubSubClient client(espClient);
คอมเม้นต์ในส่วนการสร้าง instance และการนิยามฟังก์ชันของไลบรารี Microgear ออกทั้งหมด (ถ้าในโปรแกรมมีฟังก์ชันอื่นที่เกี่ยวข้องกับ Microgear ให้คอมเม้นต์ออกด้วย)
//// ***** NETPIE 2015 Microgear instance and function declarations ******
// ---***--- MicroGear microgear(client);
// ---***--- void onMsghandler(char *topic, uint8_t* msg, unsigned int msglen) {
// ---***--- Serial.print("Incoming message --> ");
// ---***--- msg[msglen] = '\0';
// ---***--- Serial.println((char *)msg);
//
// ---***--- if (*(char *)msg == '0') digitalWrite(LED1,0);
// ---***--- else if (*(char *)msg == '1') digitalWrite(LED1,1);
// ---***--- }
//
// ---***--- void onConnected(char *attribute, uint8_t* msg, unsigned int msglen) {
// ---***--- Serial.println("Connected to NETPIE...");
// ---***--- microgear.setAlias(ALIAS);
// ---***--- }
//// **************************************************************
แทนที่ด้วยนิยามของฟังก์ชัน reconnect() ที่ใช้สำหรับเชื่อมต่อกับ NETPIE 2020
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection…");
if (client.connect(mqtt_Client, mqtt_username, mqtt_password)) {
Serial.println("connected");
client.subscribe("@msg/led");
}
else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println("try again in 5 seconds");
delay(5000);
}
}
}
และฟังก์ชัน callback() ทำหน้าที่รับข้อความที่ส่งมายังอุปกรณ์นี้
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
String message;
for (int i = 0; i < length; i++) {
message = message + (char)payload[i];
}
Serial.println(message);
if(String(topic) == "@msg/led") {
if (message == "on"){
digitalWrite(LED1,0);
client.publish("@shadow/data/update", "{\"data\" : {\"led\" : \"on\"}}");
Serial.println("LED ON");
}
else if (message == "off") {
digitalWrite(LED1,1);
client.publish("@shadow/data/update", "{\"data\" : {\"led\" : \"off\"}}");
Serial.println("LED OFF");
}
}
}
โดยในฟังก์ชันนี้จะรับคำสั่งที่ส่งมาจาก Freeboard และปิด/เปิด LED บน NodeMCU ด้วย คำอธิบายอ่านได้จากตัวอย่างในลิงก์ https://netpie.io/tutorials/NodeMCU
ในส่วนของฟังก์ชัน setup() โค้ดที่เกี่ยวข้องกับการกำหนดขา การตั้งค่าของพอร์ตอนุกรม เซนเซอร์ และการเชื่อมต่อ WiFi จะไม่มีการเปลี่ยนแปลงใดๆ ส่วนที่เปลี่ยนคือคอมเม้นต์ส่วนการตั้งค่า microgear ออก
// // ************** Microgear initialization ****************
// ---***--- microgear.on(MESSAGE,onMsghandler);
// ---***--- microgear.on(CONNECTED,onConnected);
// ---***--- microgear.init(KEY,SECRET,ALIAS);
// ---***--- microgear.connect(APPID);
// // ***************************************************
แทนด้วยการตั้งค่าสำหรับ NETPIE 2020 ซึ่งมีเพียง 2 บรรทัดเท่านั้น
// ^^^^^^^^^^^^^ initialization for NETPIE 2020 ^^^^^^^^^^^^^^^^^
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
สำหรับในส่วนของฟังก์ชัน loop() เนื่องจากเราใช้ออปเจ็ค client ของไลบรารี PubSubClient แทนออปเจ็คของไลบรารี microgear จึงคอมเม้นต์ในส่วนต้นที่มีเงื่อนไข
// ---xxx--- if (microgear.connected()) {
// ---xxx--- microgear.loop();
ออก และเพิ่มเติมเงื่อนไขใหม่เป็น
if (client.connected()) {
client.loop();
โดยจะเห็นว่ามีลักษณะการทำงานคล้ายกัน คือตรวจสอบว่าหากยังมีการเชื่อมต่ออยู่จะต้องเรียกเมธอด loop() เพื่อรักษาการเชื่อมต่อไว้
เลื่อนลงมาในส่วนของ else เมื่อเงื่อนไขไม่เป็นจริง คือพบว่าการเชื่อมต่อหลุดจะต้องทำคำสั่งเชื่อมต่อใหม่ คอมเม้นต์ของเดิมที่ใช้ microgear ออก
// ---xxx--- else {
// ---xxx--- Serial.println("connection lost, reconnect...");
// ---xxx--- microgear.connect(APPID);
// ---xxx--- }
และเปลี่ยนเป็น
else {
reconnect();
}
ซึ่งจะไปเรียกฟังก์ชัน reconnect() ที่นิยามไว้ด้านบน
การอ่านค่าจากเซนเซอร์จะคงเหมือนเดิม เว้นแต่ว่าเราไม่จำเป็นต้องตรวจสอบว่าค่าที่อ่านได้เป็นตัวเลขหรือไม่เพราะค่าที่ไม่ตรงกับรูปแบบที่กำหนดใน Device Schema จะไม่ถูกเขียน อย่างไรก็ตามอาจเลือกคงเดิมไว้ก็ได้ ดังนั้นส่วนที่เปลี่ยนแปลงคือการสร้างสตริงและพับลิช คอมเม้นต์ของเดิมที่ใช้ microgear ออก
// ---xxx--- String datastring = (String)humidity+","+(String)temperature;
// ---xxx--- Serial.print("Sending --> ");
// ---xxx--- Serial.println(datastring);
// ---xxx--- microgear.publish(DHTDATATOPIC,datastring);
แทนที่ด้วยการจัดรูปแบบสตริงแบบ JSON ที่ใช้ใน NETPIE 2020
String data = "{\"data\": {\"humidity\":" + String(humidity) +
", \"temperature\":" + String(temperature) +
", \"place\": \"" + String(place) + "\"}}";
Serial.println(data);
data.toCharArray(msg, (data.length() + 1));
client.publish("@shadow/data/update", msg);
ตัวแปร place แบบสตริงถูกเพิ่มที่หัวของโปรแกรมโดยเป็นค่าคงที่ "NECTEC Thailand" เพื่อเป็นการทดสอบการส่งค่าแบบสตริง ชื่อของ topic ที่พับลิชให้กับ NETPIE 2020 จะเป็น"@shadow/data/update" เสมอ
สังเกตว่าใน NETPIE 2020 เราไม่สามารถพับลิชข้อมูลที่เป็นตัวแปรสตริง คือ data ไปได้โดยตรง แต่ต้องแปลงให้เป็นตัวแปรแบบ character array ก่อน ดังนั้นที่ส่วนบนของโปรแกรมต้องเพิ่มนิยามตัวแปร msg ดังนี้
char msg[100];
โดยมีขนาดไม่น้อยไปกว่าจำนวนอักขระในสตริงที่ต้องการพับลิช
ส่วนสุดท้ายที่ต้องคอมเมนต์ออกไปคือการเขียน FEED เนื่องจาก NETPIE 2020 ไม่มีส่วนของ FEED แล้ว
// // ******** NETPIE 2015 FEED write ****************
// ---xxx--- newTimeWriteFeed = millis();
// ---xxx--- if(newTimeWriteFeed-lastTimeWriteFeed > 15000){
// ---xxx--- lastTimeWriteFeed = newTimeWriteFeed;
// ---xxx--- if(humidity!=0 && temperature!=0){
// ---xxx--- String feeddata = "{\"humid\":";
// ---xxx--- feeddata += humidity ;
// ---xxx--- feeddata += ", \"temp\":";
// ---xxx--- feeddata += temperature;
// ---xxx--- feeddata += "}";
// ---xxx--- Serial.print("Write Feed --> ");
// ---xxx--- Serial.println(feeddata);
// ---xxx--- //microgear.writeFeed(FEEDID,feeddata);
// ---xxx--- microgear.writeFeed(FEEDID,feeddata,FEEDAPI);
// ---xxx--- }
// ---xxx--- }
// // ************************************************
เมื่อคอมไพล์และโหลดโปรแกรม dhtled_NETPIE20.ino ลงบน NodeMCU เปิด Serial Monitor จะเห็นสตริงที่พับลิชให้กับ NETPIE 2020 ดังแสดงในรูปที่ 1

Device Schema
ดังได้กล่าวแล้วว่า NETPIE 2020 จะไม่มีหน้า FEED สำหรับเก็บข้อมูลแยกต่างหาก การแสดงผลและเก็บข้อมูลฐานเวลาจะรวมอยู่ในที่เดียวกัน และอาศัยโค้ดที่กำหนดรูปแบบการจัดเก็บข้อมูลเรียกว่า Device Schema ที่อยู่ในรูปแบบ JSON รายละเอียดอ่านได้จากลิงก์ https://docs.netpie.io/device-config.html
ในหน้า portal ของ NETPIE 2020 เลือก device ที่เชื่อมต่ออยู่กับ NodeMCU และคลิกที่ปุ่ม [Schema] เลือกการป้อนข้อมูลแบบ Code ตัวอย่างนี้จะใช้โค้ดใน Listing 2 ที่ได้จาก NETPIE 2020 Workshop โดยสามารถใส่การคำนวณขั้นพื้นฐานลงในโค้ดได้ เช่นแปลงหน่วยของอุณหภูมิจากเซลเซียสเป็นฟาร์เรนไฮต์
{
"additionalProperties": false,
"properties": {
"humidity": {
"operation": {
"store": {
"ttl": "7d"
}
},
"type": "number"
},
"temperature": {
"operation": {
"store": {
"ttl": "7d"
},
"transform": {
"expression": "(($.temperature)*1.8) + 32"
}
},
"type": "number"
},
"place": {
"operation": {
"store": {
"ttl": "7d"
}
},
"type": "string"
},
"led": {
"operation": {
"store": {
"ttl": "7d"
}
},
"type": "string"
}
}
}
Listing 2 Schema code สำหรับตัวอย่างในบทความ
เมื่อคลิกที่ปุ่ม [Shadow] จะเห็นว่า NETPIE 2020 ได้รับข้อมูลที่ส่งมาจาก NodeMCU ดังในรูปที่ 2

มาถึงขั้นนี้โปรแกรมด้าน NodeMCU ได้ถูกแก้ไขให้ใช้งานได้กับ NETPIE 2020 แล้ว สำหรับการสร้าง Freeboard ได้ถูกอธิบายไว้อย่างละเอียดแล้วในลิงก์ https://netpie.io/tutorials/NodeMCU ดังนั้นจึงจะไม่กล่าวถึงในที่นี้ รูปที่ 3 แสดงหน้า Freeboard ที่สร้างขึ้นและใช้งานได้ตามวัตถุประสงค์

สำหรับท่านที่ต้องการรันตัวอย่างโปรแกรมนี้บน ESP32 ทำได้โดยง่าย แก้ไขเพียงไลบรารี WiFi ที่ส่วนหัวของโปรแกรม โดยเปลี่ยนจาก
#include <ESP8266WiFi.h>
เป็นไลบรารีที่ใช้สำหรับ ESP32 ดังนี้
#include <WiFi.h>
และกำหนดขาที่ต่อกับเอาต์พุตของเซนเซอร์ DHT ให้ตรงกับที่ใช้จริง เช่น
#define DHTPIN 16
ในรูปที่ 4 ผู้เขียนได้ใช้บอร์ด ESP32 Dev Kit V1 ที่หาได้ทั่วไป ต่อเซนเซอร์ DHT22 เข้ากับขา 16 พบว่าใช้งานได้เหมือนกับ NodeMCU ทุกประการ (ถ้าใช้ DHT22 อย่าลิมแก้นิยาม DHTTYPE ให้ตรงกันด้วย ไม่งั้นค่าจะอ่านได้ผิดพลาด)

รวมโปรแกรมในบทความ dhtled.zip
No comments:
Post a Comment