ดิว.นินจา

ดิว.นินจา

Friday, November 30, 2018

NETPIE Microgear : การสื่อสารโดยวิธี chat และ publish

NETPIE Microgear เป็นไลบรารีสนับสนุนสำหรับการพัฒนา IoT ร่วมกับ NETPIE โดยสามารถใช้ได้กับอุปกรณ์หลายประเภททั้งแบบฮาร์ดแวร์และซอฟต์แวร์ ผู้เขียนได้อธิบายการใช้งาน Microgear ขั้นพื้นฐานแล้วทั้งในเว็บนี้และในหนังสือ แต่จากปัญหาที่ถามโดยผู้ใช้งานพบว่าในบางกรณีต้องการการเชื่อมต่อที่นอกเหนือไปจากที่เคยกล่าวถึง เช่นการสื่อสารระหว่าง IoT หลายตัว ดังนั้นจุดมุ่งหมายของบทความนี้คืออธิบายภาพรวมของการสื่อสารโดยวิธี chat และ publish พร้อมสาธิตการรับส่งข้อมูลระหว่างบอร์ด NodeMCU 2 ตัวกับ NETPIE โดยหวังว่าจะตอบโจทย์ผู้พัฒนาที่ต้องการการทำงานในลักษณะดังกล่าว

ขอเริ่มต้นโดยทบทวนความรู้พื้นฐานเกี่ยวกับ NETPIE ที่ผู้ใช้งานส่วนใหญ่ทราบดีอยู่แล้ว รูปที่ 1 แสดงองค์ประกอบหลักของเครือข่าย IoT ในระบบบัญชื NETPIE ของผู้ใช้ โดยศูนย์กลางของเครือข่ายชุดหนึ่งก็คือชื่อของแอปพลิเคชัน เรียกย่อว่า AppID ผู้ใช้สามารถมีจำนวน IoT ได้จำนวนมากเท่าที่ 100 เครดิตยังไม่ถูกใช้หมด แต่ขอบเขตของ IoT ที่สามารถสื่อสารกันได้จะต้องต่ออยู่กับ AppID เดียวกันเท่านั้น จำนวน AppID มากสุดที่มีได้ใน 1 บัญชีคือ 10 AppID

รูปที่ 1 การแบ่งขอบเขตของเครือข่าย IoT โดย AppID

ดังนั้น ประเด็นสำคัญของการเชื่อมต่อ IoT ไม่ว่าจะกี่ตัวก็ตามคือต้องอยู่ภายใต้ AppID เดียวกันเท่านั้น ส่วนสำหรับข้อมูล key, secret ของอุปกรณ์ฮาร์ดแวร์จะใช้แบบ device key ซึ่งอาจใช้ key เดียวกันหรือแยกกันก็ได้ กรณีผู้ใช้มีหลายคนแนะนำให้แยกเพราะสามารถเปลี่ยน key ของแต่ละคนได้โดยไม่กระทบส่วนรวม สำหรับส่วนที่เป็น logical เช่น browser จะใช้ session key

การสื่อสารโดยวิธี chat และ publish

ความแตกต่างระว่างวิธี chat และ publish ในไลบรารี Microgear สามารถสรุปได้ดังรูปที่ 2 และ 3 โดยในกรณีใช้วิธี chat หาก IoT ทางด้านซ้ายต้องการส่งข้อมูลให้กับ A, B, C จะต้องใช้คำสั่ง chat 3 ครั้ง จึงจะส่งได้ครบถ้วน จำนวนการใช้คำสั่ง chat จะเพิ่มตามจำนวนของผู้รับ ส่วนสำหรับกรณีใช้วิธ๊ publish ด้านตัวส่งจะ publish ข้อมูลที่นิยามโดย topic ในรูปที่ 3 คือ /home/humid ซึ่งผู้รับที่ subscribe topic /home/humid คือ A, B ก็จะได้รับข้อมูลนี้พร้อมกัน ส่วนผู้รับที่ไม่ได้ subscribe คือ C จะไม่ได้รับ ดังนั้นเมื่อพิจารณาประสิทธิภาพในการสื่อสารข้อมูล วิธี publish จะมีข้อได้เปรียบกว่าวิธี chat โดยเฉพาะเมื่อมี IoT จำนวนมาก

รูปที่ 2 การสื่อสารโดยวิธี chat
รูปที่ 3 การสื่อสารโดยวิธี publish

ยกตัวอย่าง IoT ยอดนิยม คือการส่งข้อมูลอุณหภูมิและความชื้นจาก MCU ที่ต่อกับ DHT22ไปแสดงผลบน freeboard gauges ของ NETPIE วิธีที่สะดวกคือนิยามชื่อ topic และใช้ microgear.publish() ข้อมูลทั้งหมดเป็นสตริงเดียวกัน ส่วนทางด้าน NETPIE gauge แต่ละตัวจะ subscribe topic นี้และใช้คำสั่ง split เพื่อแยกข้อมูลตัวที่ต้องการ หากมีข้อมูลอื่นที่ต้องการส่งก็สามารถรวมเป็นสตริงเดียวกันได้ มีข้อดีกว่าการส่งแต่ละข้อมูลแยกกันซึ่งอาจเกิดปัญหาด้านอัตราการส่งที่เร็วเกินไป

โจทย์ตัวอย่าง

สำหรับตัวอย่างในบทความนี้ได้จากคำถามในกลุ่ม NETPIE ผู้พัฒนาออกแบบ IoT วัดอุณหภูมิและความชื้นโดย NodeMCU ส่งค่ามาแสดงผลบน NETPIE Freeboard และมีความต้องการเพิ่มเติมคือต้องการใช้ NodeMCU อีกตัวหนึ่งรับค่าเพื่อแสดงผลบนจอ OLED ซึ่งจะมีประโยชน์สำหรับการเฝ้าดูข้อมูลในจุดที่ไม่จำเป็นต้องใช้คอมพิวเตอร์

หมายเหตุ : จากคำถามในกลุ่ม ผู้ใช้ต้องการดึงค่าข้อมูลจาก NETPIE เพื่อมาแสดงผลบน NodeMCU ตัวที่สอง แต่โดยหน้าที่หลักของ gauge widget คือรับข้อมูลและแสดงผลเท่านั้น ผู้เขียนเองไม่ทราบว่าการดึงข้อมูลดังกล่าวสามารถทำได้หรือไม่ ในทางปฏิบัติเราจะพบว่าวิธีที่ทำได้แน่นอนและสะดวกคือให้ NodeMCU ตัวแรกส่งข้อมูลให้กับทั้ง NETPIE และ NodeMCU ตัวที่สอง

โจทย์ตัวอย่างคือการพัฒนาระบบ IoT สำหรับเรือนพืชในร่มขนาดเล็ก โดยต้องการตรวจเฝ้าค่าความชื้น อุณหภูมิ และความเข้มแสงในเรือนพืชให้เหมาะสมกับการเจริญเติบโตของต้นไม้ รูปที่ 4 แสดงฮาร์ดแวร์ที่ใช้ในตัวอย่าง คือบอร์ด NodeMCU 2 ตัวประกอบบน PCB อเนกประสงค์ ทางด้านซ้ายคือบอร์ดที่ติดตั้งในเรือน มีเซนเซอร์ DHT22 วัดความชื้นและอุณหภูมิ และ BH1750 วัดความเข้มแสง และมี LED สีส้มขนาด 10 mm แทนหลอดไฟสำหรับการสังเคราะห์แสงของพืช ตั้งชื่อ ALIAS ของ NodeMCU ตัวนี้ว่า N01 ส่วนทางด้านขวาคือ NodeMCU ชื่อ N02 ทำหน้าที่รับข้อมูลจาก N01 เพื่อแสดงผลบน OLED

เพื่อเพิ่มความน่าสนใจของโจทย์ตัวอย่างนี้ ที่ตัว N02 มีตัวต้านทานปรับค่าได้ต่อกับขาแอนะล็อก A0 เพื่อปรับความสว่างของหลอด LED บนบอร์ด N01 ค่าข้อมูลจากทั้งสองบอร์ด คือ ความชื้น อุณหภูมิ ความเข้มแสง และค่าความสว่างหลอดไฟ จะถูกแสดงผลบน NETPIE Freeboard

รูปที่ 4 NodeMCU บน PCB อเนกประสงค์สำหรับโจทย์ตัวอย่าง

เพื่อสาธิตการสื่อสารข้อมูลทั้งสองแบบ เราจะให้ N01 ส่งข้อมูลโดยวิธี publish และ N02 ส่งโดยวิธี chat

สร้าง Application และ keys ในบัญชี NETPIE

เริ่มต้นการพัฒนาโดยสร้างศูนย์กลางการเชื่อมต่อในบัญชี NETPIE ของเรา คือ แอปพลิเคชัน ในตัวอย่างตั้งชื่อ AppID ว่า dewGreenhouse (ผู้อ่านต้องตั้งเป็นชื่อของตัวเองที่ไม่ซ้ำใคร) สร้าง device key สำหรับ NodeMCU ทั้งสองตัว ชื่อ greenhousedevkey และ session key สำหรับ Freeboard ชื่อ greenhouseseskey ดังแสดงในรูปที่ 5

รูปที่ 5 สร้าง NETPIE AppID สำหรับโจทย์ตัวอย่าง

การ publish ข้อมูลโดยบอร์ด N01

ในช่วงต้นของตัวอย่างจะสาธิตวิธี publish โดยบอร์ด N01 ก่อน ด้านรับข้อมูลคือ N02 และ Freeboard ที่ subscribe topic เดียวกัน ส่วนการ chat โดย N02 จะกล่าวถึงในช่วงหลัง

หน้าที่ของบอร์ด N01 คืออ่านค่าจากเซนเซอร์วัดความชื้น อุณหภูมิ (DH 22) และความเข้มแสง (BH1750) และ publish ค่าทั้งสามในสตริงเดียวกัน การอ่านค่าจากเซนเซอร์จะอาศัยไลบรารีสนับสนุนซึ่งผู้อ่านส่วนใหญ่คงได้ศึกษาการโปรแกรมในส่วนนี้มาแล้ว รวมถึงโค้ดการเชื่อมต่อ WiFi และการเริ่มต้นเชื่อมต่อกับ NETPIE โดยไลบรารี Microgear การกำหนดเหตุการณ์ต่างๆ ฯลฯดังนั้นจะกล่าวถึงรายละเอียดเฉพาะส่วนที่เป็นเนื้อหาหลักของบทความ

ที่ส่วนหัวของโปรแกรม ใส่นิยามของ APPID, KEY, SECRET ที่ NETPIE กำหนดให้


#define APPID   "dewGreenhouse"
#define KEY     "aa8JndapvJ5avM"
#define SECRET  "lrQRPMDnxUQ7jgzcTpxOI6u"

ตั้งชื่อเรียกแทนอุปกรณ์นี้ว่า N01 และนิยาม N02 เป็นเพื่อนบ้าน


#define ALIAS   "N01"               
#define NEIGHBOR "N02"   

นิยามชื่อ topic ที่ต้องการ publish


#define DHTLIGHTDATATOPIC "/dhtlight/" ALIAS

ค่าของความชื้น อุณหภูมิ และความเข้มแสง ถูกเก็บในตัวแปร h, t, lux ตามลำดับ ฟังก์ชัน loop() อ่านค่า h, t ทุก 2 วินาที (ข้อจำกัดของ DHT 22) และตรวจสอบว่าเป็นค่าตัวเลขหรือไม่ ก่อนจะสร้างสตริง


String datastring = (String)h+","+(String)t+","+(String)lux;

และ publish สตริงนี้ออกไปให้ผู้รับ


microgear.publish(DHTLIGHTDATATOPIC,datastring);

พร้อมกับส่งค่าออกพอร์ตอนุกรมเพื่อตรวจสอบ


Serial.print("Sending --> ");
Serial.println(datastring);

โหลดโปรแกรม N01.ino ลงบนบอร์ด เปิด Serial Monitor จะเห็นสตริงที่ถูก publish ดังเช่นในรูปที่ 6

รูปที่ 6 ตรวจสอบสตริงที่ publish โดย Serial Monitor

สร้าง gauge widgets บน NETPIE Freeboard

บทความนี้จะไม่อธิบายการสร้าง gauge เพื่อแสดงผลบน Freeboard โดยละเอียด ขั้นตอนหลักคือผู้ใช้สร้าง Freeboard ใหม่ขึ้นมา สร้าง datasource เป็นชนิด NETPIE microgear ใส่ค่า key, secret ของ greenhouseseskey ที่สร้างไว้ก่อนหน้านี้ เลือก add pane และสร้าง gauges 3 ตัวสำหรับแสดงค่า ความชื้น (Humid) อุณหภูมิ (Temp) ความเข้มแสง (Light) โดยใส่ค่าดังนี้


datasources["dewghds"]["/dewGreenhouse/dhtlight/N01"].split(",")[0]
datasources["dewghds"]["/dewGreenhouse/dhtlight/N01"].split(",")[1]
datasources["dewghds"]["/dewGreenhouse/dhtlight/N01"].split(",")[2]

ลงในช่อง VALUE ของ gauge แต่ละตัวตามลำดับ คำสั่ง .split(",")[x] ในส่วนท้ายทำหน้าที่แยกข้อมูลที่คั่นโดยเครื่องหมาย "," ออกจากกัน โดยค่าตัวชี้ x เริ่มจาก 0 แทนค่าแรก (ความชื้น)

เมื่อกำหนดทุกอย่างถูกต้อง จะได้การแสดงผลบน NETPIE Freeboard ดังในรูปที่ 7

รูปที่ 7 gauge widgets บน NETPIE Freeboard แสดงค่าความชื้น อุณหภูมิ และความเข้มแสง

สังเกตชื่อ topic ที่ gauges ทั้งสามตัวอ้างถึงอยู่ในรูป {APPID}/{ชื่อ topic ที่นิยาม}/{ALIAS} ในตัวอย่างนี้คือ /dewGreenhouse/dhtlight/N01

การ subscribe เพื่อรับข้อมูลโดย N02

จากโจทย์ที่ตั้งไว้ ต้องการให้บอร์ด N02 รับค่าจาก topic เดียวกันที่ N01 publish ให้กับ Freeboard และแสดงค่าบน OLED ที่ส่วนหัวของโปรแกรม N02.ino ใส่นิยามของ APPID, KEY, SECRET โดยใช้ข้อมูลเดียวกับในโปรแกรม N01


#define APPID   "dewGreenhouse"
#define KEY     "aa8JndapvJ5avM"
#define SECRET  "lrQRPMDnxUQ7jgzcTpxOI6u"

ตั้งชื่อเรียกแทนอุปกรณ์นี้ว่า N02 และนิยาม N01 เป็นเพื่อนบ้าน


#define ALIAS   "N02"               
#define NEIGHBOR "N01"   

การ subscribe topic จะใช้คำสั่ง microgear.subscribe() ตำแหน่งที่เหมาะสมในการใส่คำสั่งนี้คือในฟังก์ชัน onConnected()


void onConnected(char *attribute, uint8_t* msg, unsigned int msglen) {
    Serial.println("Connected to NETPIE...");
    microgear.setAlias(ALIAS);
    microgear.subscribe("/dhtlight/N01");
}

โดยคำสั่งนี้ N02 จะ subscribe topic /dhtlight/N01 ที่ publish โดย N01 เมื่อการเชื่อมต่อ NETPIE สำเร็จ

ข้อสังเกต : ชื่อ topic นี้ไม่ต้องนำหน้าด้วย APPID dewGreenhouse แตกต่างจากที่ใช้ใน datasource ของ Freeboard

เมื่อ subscribe แล้ว ข้อมูลที่ publish โดย N01 จะถูกรับโดยฟังก์ชัน onMsghandler() งานที่เหลือจากนี้ก็คือจะต้องแยกข้อมูล ความชื้น อุณหภูมิ และความเข้มแสง ที่คั่นโดย ',' ออกจากกัน ในภาษา C ของ Arduino ไม่มีคำสั่ง split() ดังนั้นต้องเขียนในส่วนนี้เองโดยอาศัยฟังก์ชันจัดการสตริง สามารถทำได้หลายวิธี เนื่องจากจำนวนข้อมูลมีเพียง 3 ค่าในตัวอย่างนี้จะแสดงวิธีการอย่างง่ายที่ผู้เขียนใช้แล้วได้ผลดี ฟังก์ชัน onMsghandler() ทั้งหมดเขียนได้ดังนี้


void onMsghandler(char *topic, uint8_t* msg, unsigned int msglen) {
    //Serial.print("Incoming message --> ");
    char *m = (char *)msg;  // needed to avoid conversion error
    m[msglen] = '\0';    
    rcvdstring = m;
    int strIndex = rcvdstring.indexOf(',');
    String subStr = rcvdstring.substring(0, strIndex); // extract humidity data
    h = subStr.toFloat();
    rcvdstring = rcvdstring.substring(strIndex+1); // truncate humidity data
    strIndex = rcvdstring.indexOf(',');
    subStr = rcvdstring.substring(0, strIndex); // extract temperature data
    t = subStr.toFloat();    
    rcvdstring = rcvdstring.substring(strIndex+1); // the rest is light intensity data
    l = rcvdstring.toFloat();
    showOLED(h,t,l);
}

โดยหลังจากแยกสตริงของข้อมูลแล้วได้เก็บไว้ในตัวแปรแบบ float เพื่อความสะดวกหากต้องการประมวลผลต่อไป เช่นเปรียบเทียบว่าความชื้น อุณหภูมิ ความเข้มแสง สูงหรือต่ำกว่าค่าที่กำหนดหรือไม่และให้แจ้งเตือน บรรทัดสุดท้ายคือฟังก์ชัน showOLED() ที่เขียนขึ้นสำหรับการแสดงผลออก OLED SSD1306 ของ Adafruit (ผู้อ่านสามารถดูฟังก์ชันได้จากโปรแกรมทั้งหมดท้ายบทความ)

เมื่อคอมไพล์และโหลดโปรแกรมลงบนบอร์ด N02 และรอจนสามารถเชื่อมต่อ NETPIE สำเร็จ จะเห็นการแสดงข้อมูลความชื้น อุณหภูมิ และความเข้มแสงบนจอ OLED ดังในรูปที่ 8

รูปที่ 8 การแสดงข้อมูลบนจอ OLED ของบอร์ด N02

การควบคุมความสว่าง LED บน N02 โดยวิธี chat จาก N01

การสาธิตขั้นสุดท้ายในตัวอย่างนี้คือ ต้องการควบคุมความสว่างของ LED สีส้มขนาด 10 มม. บนบอร์ด N01 โดยตัวต้านทานปรับค่าได้ที่ต่อกับขาแอนะล็อก A0 บนบอร์ด N02 โดยใช้วิธี chat และแสดงค่าความสว่างหลอดไฟนี้บน NETPIE Freeboard ด้วย (หน่วยเป็นค่าที่อ่านได้จากขาแอนะล็อกในช่วง 0 – 1023)

ในกรณีของการใช้วิธี chat ในตัวอย่างนี้จะเห็นว่า N02 ต้องส่งข้อมูลความสว่างหลอดไฟให้กับ 2 ผู้รับ คือ N01 และ widget แสดงผลบน NETPIE Freeboard ดังนั้นหลังจากอ่านค่าจาก A0 จะต้องใช้คำสั่ง chat 2 ครั้ง ตามจำนวนผู้รับ


lampvalue = analogRead(A0);    // read from VR
microgear.chat(NEIGHBOR,(String)lampvalue);  // chat to N01
microgear.chat("N02/lampvalue",(String)lampvalue); // chat to NETPIE Freeboard

การ chat ครั้งแรกคือส่งไปหา N01 ที่นิยามไว้เป็น NEIGHBOR สำหรับการเพิ่มเติมโค้ดทางด้าน N01 เพื่อปรับความสว่างของ LED มีตรงส่วนของฟังก์ชัน onMsghandler() ที่รับค่าความสว่างในรูปสตริงและแปลงค่าเก็บในตัวแปรแบบ int


void onMsghandler(char *topic, uint8_t* msg, unsigned int msglen) {
    //Serial.print("Incoming message --> ");
    char *m = (char *)msg;  // needed to avoid conversion error
    m[msglen] = '\0';    
    rcvdstring = m;
    lampvalue=rcvdstring.toInt();
}

และใส่คำสั่งเพื่อส่งค่าออกเอาต์พุตในฟังก์ชัน loop()


analogWrite(LAMP, lampvalue);   // adjust lamp brightness

โดย LAMP นิยามไว้เป็นขา D5 ที่ต่อกับ LED สีส้มขนาด 10 มม. เมื่อคอมไพล์และโหลดโปรแกรมที่แก้ไขแล้วลงบน N01 ทดลองปรับค่า VR บน N02 ดังในรูปที่ 9 จะเห็นว่าสามารถควบคุม LED ได้ตามต้องการ โดยมีการหน่วงเวลาบ้างตามอัตราการรับส่งข้อมูลที่จำกัดโดย NETPIE

รูปที่ 9 การปรับความสว่างของ LED บนบอร์ด N01 โดย VR บนบอร์ด N02

การตั้งค่า widget บน NETPIE Freeboard เพื่อรับข้อมูลโดยวิธี chat

จากคำสั่งที่ใส่ไว้ในโปรแกรม N02.ino สำหรับ chat ไปหา NETPIE Freeboard คือ


microgear.chat("N02/lampvalue",(String)lampvalue); // chat to NETPIE Freeboard

โดย lampvalue คือตัวแปรที่นิยามไว้ในโปรกรม N02.ino สำหรับเก็บค่าที่อ่านได้จากขาแอนะล็อก เราจะทดลองใช้ widget แบบ Sparkline เพื่อรับข้อมูลนี้ เพิ่ม widget และตั้งค่าดังแสดงในรูปที่ 10

รูปที่ 10 การตั้งค่า Sparkline widget เพื่อรับข้อมูลที่ chat มาจาก N02

ส่วนสำคัญคือค่าที่ใส่ในช่อง VALUE


datasources["dewghds"]["/dewGreenhouse/gearname/N02/lampvalue"] 

ที่จะมีขึ้นให้คลิกเลือกหลังจากที่รันโปรแกรม N02.ino แล้ว มีรูปแบบคือ /{APPID}/gearname/{ALIAS/var} โดย ALIAS/var ถูกระบุในฟังก์ชัน microgear.chat() ทางด้านผู้ส่ง เมื่อคลิก SAVE จะเห็นว่า Sparkline widget ที่สร้างขึ้นใหม่สามารถรับข้อมูลจากตัวแปร lampvalue ของ N02 ได้ ทดลองปรับค่า VR จะได้การแสดงผลดังรูปที่ 11

รูปที่ 11 Freeboard ที่เพิ่ม Sparkline widget รับข้อมูลที่ chat มาจาก N02

สรุป

บทความนี้สาธิตการสื่อสารข้อมูลระหว่าง IoT ที่เชื่อมต่อกับ APPID ของ NETPIE โดยวิธี publish และ chat จะพบว่าเมื่ออุปกรณ์มีจำนวนมากขึ้น ข้อได้เปรียบของวิธี publish เมื่อเทียบกับวิธี chat จะยิ่งชัดเจนขึ้น การตั้งชื่อ topic และการเลือก topic เพื่อ subscribe เป็นกลไกที่สามารถช่วยจัดการเครือข่ายที่มี IoT หลายตัวได้อย่างมีประสิทธิภาพ

  • รวมโปรแกรมที่ใช้ในตัวอย่าง NETPIEchatpublish.zip
  • วีดีโอแสดงการทำงานร่วมกันของ N01, N02 และ Freeboard

No comments:

Post a Comment

แนะนำหนังสือ “ตัวควบคุมป้อนกลับบนอินเทอร์เน็ตโดย ESP8266”

ปัจจุบันเมื่อกล่าวถึงอุปกรณ์ IoT (Internet of Things) คงมีน้อยคนที่จะไม่รู้จัก ในยุคที่การเข้าถึงอินเทอร์เน็ตเป็นกิจวัตรประจำวันของมนุษย์เ...