建立可透過 MCS Lite 控制的 Beacon
Last updated
Last updated
本教學將示範建構 IoT 綜合應用系統,以展示如何達成區網內的裝置通訊、以及連接外網的系統組合。在此應用情境中,主要構成元件如下:
IoT gateway:由具有高效處理能力與傳輸效能的 LinkIt Smart 7688 構成。所有在 LinkIt Smart 7688 私有區網內的節點皆透過此 gateway 連接到外部的網際網路。
終端節點:使用 LinkIt 7697 作為輕量與節能的 IoT 終端平台。
使用者的移動裝置 (如手機等):作為與終端節點互動以及控制 gateway 的平台。
接下來的章節,將說明上述元件的設置方法;希望藉由這些範例幫助開發者了解其運作機制,並以此為基礎擴充至不同的 IoT 應用場景。
作為硬體資源比終端節點更強的平台,gateway 主要功能為資料處理與傳輸。LinkIt Smart 7688 在此例中,被設置為 MCS Lite 伺服器,提供私有雲服務處理區網內產生的資料點。此外,LinkIt Smart 7688 並提供 Wi-Fi repeater 功能,使區網內的節點得以連接網際網路。下列兩篇教學文章說明如何將 LinkIt Smart 7688 設置為 MCS Lite 伺服器以及如何使 LinkIt Smart 7688 運作在 Wi-Fi repeater 的中繼模式:
此外請參閱另一篇教學文件,建立可控制 LinkIt 7697 板上 LED 的 MCS Lite 測試裝置,此裝置也會被應用在本文的綜合範例當中。
測試裝置所包含的重要資訊有:
Device id
Device key
名為 switch_display 的開/關顯示器通道
名為 switch_controller 的開/關控制器通道
當撰寫 LinkIt 7697 的 Arduino sketch 程式碼時,開發者需提供這些資訊至對應的 MCS Lite API 之中。
請先參閱另外兩篇相關主題的教學:
接下來的範例將整合上述文章,將 LinkIt 7697 設置為可受 MCS Lite 控制的 BLE beacon (用來廣播 MCS Lite 控制頁面的 URL)。在此應用下,當使用者裝置 (如已開啟藍芽的手機) 靠近 7697 節點時,會自動收到 MCS Lite 控制頁面的網址資訊,不需為了連結頁面而手動輸入網址。使用的程式碼整合自前述的兩篇教學,主要修改處將會在下列章節說明。若要取得完成的 sketch 程式碼,請參考文末的參考資料章節。
程式一開始,開發者需設定 IoT gateway 的 SSID 與密碼等連線資訊,讓 LinkIt 7697 能加入區域網路並連接到 MCS Lite 的私有雲服務。
// Assign AP ssid / password here
#define _SSID "YOUR_AP_NAME"
#define _KEY "YOUR_PASSWORD"
基於這些資訊,LinkIt 7697 會透過 58 行的程式連線到 gateway 所提供的 Wi-Fi AP:
Serial.print("WiFi.begin(");
Serial.print(_SSID);
Serial.print(",");
Serial.print(_KEY);
Serial.println(")...");
WiFi.begin(_SSID, _KEY);
雖然基於安全理由不建議這麼做,但若開發者欲連接至無密碼設定的 Wi-Fi AP,則需將 58 行的 API 如下修改,才能使 LinkIt 7697 順利連接該 AP:
WiFi.begin(_SSID);
欲取得與 MCS Lite 伺服器的連線,需在 API 中指定伺服器位置以及 LinkIt 7697 測試裝置所對應的 device id 和 device key。修改程式碼第 14 行的值以提供正確連線資訊:
MCSLiteDevice mcs("YOUR_DEVICE_ID", "YOUR_DEVICE_KEY", "MCS_LITE_SERVER_ADDRESS", MCS_LITE_SERVICE_PORT);
請依照 MCS Lite 控制頁面的 device id 與 device key 資訊填入前兩個欄位;而描述 MCS Lite 伺服器位置的 IP 與通訊埠欄位,可透過啟動 MCS Lite 伺服器時所顯示的資訊取得。
建立這個範例的測試裝置時,會定義顯示器與控制器資料通道。因此在 sketch 裡需指定對應的通道資訊以供伺服器識別:
MCSControllerOnOff led("switch_controller");
MCSDisplayOnOff remote("switch_display");
為了讓使用者輕易地存取 MCS Lite 網頁控制介面,IoT 終端節點會透過 BLE beacon 機制不斷廣播 MCS Lite 頁面的 URL。當使用者平台 (如手機) 支援 BLE 並裝有能識別 Eddystone URL beacon 的應用程式時,就能自動從節點裝置獲得 MCS Lite URL 的資訊。依照 Eddystone 定義的格式,修改第 44 行程式碼以進行 URL 廣播:
beaconData.configAsEddystoneURL(EDDY_HTTPS, "goo.gl/evYXvt");
由於 Eddystone URL 有長度限制 (17 bytes),開發者可搭配任一縮網址服務將欲廣播的 URL 進行簡化。在此範例中,使用的 URL "http://mylinkit.local:3000" 需被縮短為 "goo.gl/evYXvt" 後,才符合 Eddystone 的長度規範。關於更多 Eddystone URL 的細節,請參考 7697 Beacon 教學的 "使用 LinkIt 7697 作為 Eddystone-URL Beacon" 章節。
注意
在進行下列步驟前,請開啟使用者平台的 Wi-Fi 與 BLE 功能,並確認已連接到 IoT gateway。
為了識別 Eddystone 廣播資訊,使用者需安裝支援搜尋 Eddystone URL beacon 的應用程式,以下步驟將採用 Physical Web 應用程式作為示範。
安裝後,若在 LinkIt 7697 附近開啟該應用程式,則會看到 beacon 廣播的 URL 如下:
除了透過開啟應用程式取得 URL 外,亦支援以 widget 模式讀取 beacon 資訊:
點選該 URL 即會被導向 URL 所指的 MCS Lite 控制頁面:
登入 MCS Lite 服務之後,即可透過手機取得與控制 LinkIt 7697 LED 的狀態:
以下為 LinkIt 7697 所執行程式的完整 Arduino sketch 碼:
#include <LWiFi.h>
#include <WiFiClient.h>
#include "MCS.h"
#include <LBLE.h>
#include <LBLEPeriphral.h>
// Assign AP ssid / password here
#define _SSID "YOUR_AP_NAME"
#define _KEY "YOUR_PASSWORD"
// Assign device id / key of your test device
//MCSDevice mcs("YOUR_DEVICE_ID", "YOUR_DEVICE_KEY");
MCSLiteDevice mcs("YOUR_DEVICE_ID", "YOUR_DEVICE_KEY", "MCS_LITE_SERVER_ADDRESS", MCS_LITE_SERVICE_PORT);
// Assign channel id
// The test device should have 2 channel
// the first channel should be "Controller" - "On/Off"
// the secord channel should be "Display" - "On/Off"
MCSControllerOnOff led("switch_controller");
MCSDisplayOnOff remote("switch_display");
#define LED_PIN 7
void setup() {
// setup Serial output at 9600
Serial.begin(9600);
// setup LED/Button pin
pinMode(LED_PIN, OUTPUT);
// Initialize BLE subsystem
Serial.println("BLE begin");
LBLE.begin();
while (!LBLE.ready()) {
delay(100);
}
Serial.println("BLE ready");
// configure our advertisement data as iBeacon.
LBLEAdvertisementData beaconData;
// make an Eddystone-URL beacon that this board casts
beaconData.configAsEddystoneURL(EDDY_HTTPS, "goo.gl/evYXvt");
Serial.print("Start advertising Eddystone-URL");
// start advertising it
LBLEPeripheral.advertiseAsBeacon(beaconData);
// setup Wifi connection
while(WL_CONNECTED != WiFi.status())
{
Serial.print("WiFi.begin(");
Serial.print(_SSID);
Serial.print(",");
Serial.print(_KEY);
Serial.println(")...");
WiFi.begin(_SSID);
}
Serial.println("WiFi connected !!");
// setup MCS connection
mcs.addChannel(led);
mcs.addChannel(remote);
while(!mcs.connected())
{
Serial.println("MCS.connect()...");
mcs.connect();
}
Serial.println("MCS connected !!");
// read LED value from MCS server
while(!led.valid())
{
Serial.println("read LED value from MCS...");
led.value();
}
Serial.print("done, LED value = ");
Serial.println(led.value());
digitalWrite(LED_PIN, led.value() ? HIGH : LOW);
}
void loop() {
// call process() to allow background processing, add timeout to avoid high cpu usage
mcs.process(100);
// updated flag will be cleared in process(), user must check it after process() call.
if(led.updated())
{
Serial.print("LED updated, new value = ");
Serial.println(led.value());
digitalWrite(LED_PIN, led.value() ? HIGH : LOW);
if(!remote.set(led.value()))
{
Serial.print("Failed to update remote");
Serial.println(remote.value());
}
}
// check if need to re-connect
while(!mcs.connected())
{
Serial.println("re-connect to MCS...");
mcs.connect();
if(mcs.connected())
Serial.println("MCS connected !!");
}
}