เปิดหน้า Dashboard แล้วทำไมยังไม่เห็นค่าเซนเซอร์

เวลาเปิดหน้า Dashboard ของเซนเซอร์ บางครั้งเราจะเห็นช่องว่างอยู่พักหนึ่ง ทั้งที่อุปกรณ์ยังทำงานและก่อนหน้านี้ก็ส่งค่ามาตามปกติ ถ้าตรวจแล้วพบว่าหน้าเว็บเพิ่ง subscribe เข้ามาหลังรอบส่งล่าสุด ก็เริ่มเข้าใจว่ามันกำลังรอข้อมูลรอบใหม่อยู่
งานที่ส่งค่าถี่อาจทำให้ช่วงนี้สั้นจนแทบไม่รู้สึก แต่ถ้าอุปกรณ์ต้องประหยัดแบตและส่งห่างกันหลายนาที คนที่เพิ่งเปิดหน้าก็อาจต้องรอนานตามไปด้วย จึงเกิดคำถามว่าเราจะให้ผู้รับใหม่เห็นค่าล่าสุดที่เคยมีได้อย่างไร โดยไม่ต้องสั่งให้ทุกอุปกรณ์ตื่นมาส่งใหม่ทันที
MQTT มี retained message สำหรับงานลักษณะนี้ครับ แต่ก่อนเปิดใช้ก็ควรแยกให้ชัดว่าค่าที่ได้หมายถึงสิ่งที่ broker จำไว้ล่าสุด ไม่ได้ยืนยันด้วยตัวมันเองว่าอุปกรณ์ยังออนไลน์หรือเพิ่งวัดค่านั้นมา
Broker จำข้อความล่าสุดไว้ตรงชื่อที่ส่งมา
เวลาผู้ส่ง publish โดยตั้ง retain ไว้ broker จะจัดการข้อความที่เก็บไว้สำหรับ topic นั้นตามกติกาของ protocol เมื่อมีผู้รับใหม่ที่มีตัวกรองตรงกัน ก็สามารถได้รับข้อความที่เก็บไว้นั้นได้ โดยไม่จำเป็นต้องรอให้เซนเซอร์ส่งรอบถัดไปก่อน
ลองนึกถึง topic อุณหภูมิของห้องหนึ่ง ถ้าอุปกรณ์เคยส่งค่าไว้แล้วคนเปิดหน้าจอเข้ามาทีหลัง หน้าจอก็ได้รับค่าล่าสุดที่เก็บไว้เพื่อใช้เริ่มแสดงผลได้ หลังจากนั้นจึงรับข้อมูลใหม่ตามที่อุปกรณ์ส่งเข้ามาต่อไป วิธีนี้ช่วยลดช่วงที่หน้าจอดูเหมือนไม่มีข้อมูล ทั้งที่ระบบเคยรู้ค่าของห้องนั้นแล้ว

สิ่งที่ต้องออกแบบคู่กันคือความหมายของคำว่าล่าสุด ถ้าอุปกรณ์ไม่ได้ส่งมาหลายชั่วโมง ค่าที่ broker จำไว้ก็อาจยังเป็นค่าเดิม จึงควรให้ payload บอกเวลาวัดหรือข้อมูลที่ช่วยตัดสินความสดได้ด้วย แทนการอ้างเวลาที่หน้าเว็บได้รับข้อความเพียงอย่างเดียว
เวลาวัดกับเวลาที่ได้รับควรแยกออกจากกัน
เซนเซอร์อาจวัดค่าก่อนส่ง และบางระบบยังมีคิวรอส่งอีกชั้นด้วย เวลาที่หน้าเว็บได้รับจึงอาจห่างจากเหตุการณ์ที่ต้องการแสดง ถ้าเอาเวลารับมาตั้งเป็นเวลาอัปเดตของข้อมูลอย่างเดียว คนอ่านก็อาจเข้าใจว่าค่านั้นเกิดขึ้นในขณะเปิดหน้า
ตัวอย่างรูปแบบ payload อาจมีทั้งค่า หน่วย และเวลาวัด เช่นเดียวกับข้อมูลที่ใช้เก็บย้อนหลัง โดยฟิลด์เวลาต้องมีข้อตกลงชัดว่ามาจากแหล่งใดและอยู่ในรูปแบบไหน หากอุปกรณ์ยังไม่มีเวลาที่เชื่อถือได้ ก็ต้องออกแบบทางเลือกให้เหมาะกับข้อจำกัดนั้น แทนการเติมเวลาที่ดูถูกต้องแต่ไม่มีที่มา
ฝั่งหน้าเว็บจึงสามารถแสดงได้ทั้งค่าล่าสุดกับสถานะความสด เช่น บอกว่าอัปเดตเมื่อใด หรือแยกกรณีที่ยังไม่เคยมีข้อมูลกับกรณีที่ข้อมูลเก่าแล้ว วิธีนำเสนอนี้ช่วยให้คนใช้งานตัดสินใจได้ดีกว่าทำให้ทุกช่องมีตัวเลขอยู่เสมอ
Retained message ไม่ใช่ประวัติทุกค่าที่เคยส่ง
พอเริ่มใช้แล้ว อาจรู้สึกว่า broker เก็บข้อมูลให้เราอยู่ จนเผลอคาดหวังว่าจะเรียกดูย้อนหลังหลายชั่วโมงได้ด้วย แต่ retained message มีหน้าที่เป็นค่าที่เก็บไว้ตาม topic ไม่ใช่ฐานข้อมูลประวัติที่เก็บทุกตัวอย่างเรียงตามเวลา
ถ้าต้องการดูแนวโน้มอุณหภูมิหรือคำนวณข้อมูลย้อนหลัง ก็ควรมีผู้รับที่เก็บข้อความเข้าแหล่งข้อมูลที่ออกแบบไว้ต่างหาก ส่วน retained message ใช้ช่วยให้ผู้รับใหม่เริ่มรู้สถานะล่าสุดได้ ทั้งสองส่วนจึงทำงานร่วมกันได้โดยไม่ต้องให้ส่วนหนึ่งแทนอีกส่วนหนึ่ง

การแยกหน้าที่นี้ยังช่วยตอนกำหนดอายุข้อมูลด้วย เช่น หน้าจออาจไม่แสดงสถานะที่เก่าเกินเงื่อนไข แม้ฐานข้อมูลยังเก็บไว้ให้วิเคราะห์ต่อได้ ส่วนข้อมูลย้อนหลังจะลบเมื่อใดก็เป็นนโยบายอีกเรื่องหนึ่ง ไม่ควรผูกว่าการลบ retained message ต้องลบประวัติทั้งหมดตามไปด้วย
สถานะกับคำสั่งไม่ได้เหมาะกับการเก็บค้างเหมือนกัน
ค่าที่บอกว่าอุปกรณ์กำลังอยู่ในสถานะใด มักมีเหตุผลให้ผู้รับใหม่อยากรู้ทันที แต่คำสั่งที่ทำงานครั้งเดียว เช่น ให้เริ่มกระบวนการหนึ่งรอบ อาจมีผลอีกแบบถ้ามันถูกส่งกลับมาให้ปลายทางหลัง reconnect
ก่อนเปิด retain กับ topic คำสั่ง จึงควรดูว่าคำสั่งนั้นเป็นสถานะที่ต้องการให้คงอยู่หรือเป็นเหตุการณ์ที่ต้องทำเพียงครั้งเดียว และปลายทางมีวิธีตรวจคำสั่งซ้ำหรือไม่ การใช้ชื่อ topic แยก command กับ state ช่วยให้กำหนดกติกาเหล่านี้ได้ชัดขึ้น แต่ยังต้องออกแบบฝั่งแอปให้ตรงความหมายด้วย
หากอุปกรณ์ถูกย้ายที่หรือเปลี่ยนหน้าที่ ก็ต้องจัดการค่าค้างที่ชื่อเดิมด้วย MQTT มีกติกาสำหรับลบ retained message โดยส่งข้อความ retained ที่มี payload ว่างไปยัง topic นั้น ซึ่งต่างจากการส่งข้อความคำว่า null เป็นเนื้อหาธรรมดา ควรทดสอบด้วยเครื่องมือที่ใช้จริงก่อนนำไปทำงานอัตโนมัติ
ลองทดสอบด้วยคนส่งและคนรับที่เริ่มคนละเวลา
วิธีตรวจที่เข้าใจง่ายคือเริ่มจากให้ผู้ส่งส่งสถานะที่ตั้ง retain ไว้ แล้วค่อยเปิดผู้รับใหม่ที่ subscribe ชื่อตรงกัน ดูว่าผู้รับได้รับข้อมูลโดยยังไม่ต้องสั่งส่งรอบใหม่หรือไม่ จากนั้นลองเปลี่ยนค่าแล้วเปิดผู้รับอีกชุด เพื่อดูว่าค่าที่เก็บถูกอัปเดตตามที่คิดหรือเปล่า
ต่อด้วยกรณีที่หยุดผู้ส่งไว้สักช่วงหนึ่ง แล้วเปิดหน้าจอใหม่อีกครั้งเพื่อดูว่าหน้าจอสื่อความเก่าของข้อมูลได้ชัดหรือยัง หากต้องการทดสอบการเก็บข้ามการเริ่ม broker ใหม่ ก็ต้องตรวจการตั้งค่าการจัดเก็บของ broker เพิ่มด้วย เพราะความต่อเนื่องบนดิสก์เป็นรายละเอียดของระบบที่นำมาใช้
อีกกรณีที่ควรลองคือผู้รับคนละสิทธิ์ เพราะการมีข้อความเก็บอยู่ไม่ได้หมายความว่าทุกบริการควรอ่านได้เหมือนกัน หน้า Dashboard ที่แสดงข้อมูลให้คนทั่วไปอาจต้องรับผ่านบริการกลางที่เลือกฟิลด์ให้แล้ว ขณะที่เครื่องมือดูแลระบบอาจมีสิทธิ์อ่านละเอียดกว่า จึงควรตรวจผลด้วยบัญชีที่แต่ละระบบใช้จริงด้วย
หากมีการย้ายชื่อ topic ก็ควรทำรายการชื่อเก่าที่ต้องล้างคู่กัน มิฉะนั้นหน้าจอหรือผู้รับที่ยังใช้การสมัครแบบกว้างอาจเห็นทั้งอุปกรณ์เดิมกับอุปกรณ์ใหม่พร้อมกัน การจัดการ retained message จึงควรเป็นส่วนหนึ่งของการย้ายรุ่นข้อมูล ไม่ใช่คิดถึงเฉพาะตอนเริ่มส่งค่าแรกครับ
สรุป
Retained message ช่วยให้ผู้รับใหม่เริ่มต้นจากค่าล่าสุดที่ broker เก็บไว้ได้ จึงเหมาะกับการลดช่วงรอข้อมูลเมื่อเปิด Dashboard แต่ต้องแสดงความสดของค่านั้นให้เข้าใจ และแยกออกจากประวัติย้อนหลังกับคำสั่งที่ไม่ควรถูกทำซ้ำ เมื่อกำหนดความหมายและวิธีล้างค่าค้างไว้ครบ ก็จะได้หน้าจอที่เปิดมาแล้วรู้สถานะได้เร็วขึ้นโดยไม่ทำให้คนใช้เข้าใจข้อมูลเก่าผิดไปครับ


