# 建立可透過 MCS Lite 控制的 Beacon

本教學將示範建構 IoT 綜合應用系統，以展示如何達成區網內的裝置通訊、以及連接外網的系統組合。在此應用情境中，主要構成元件如下：

1. IoT gateway：由具有高效處理能力與傳輸效能的 LinkIt Smart 7688 構成。所有在 LinkIt Smart 7688 私有區網內的節點皆透過此 gateway 連接到外部的網際網路。
2. 終端節點：使用 LinkIt 7697 作為輕量與節能的 IoT 終端平台。
3. 使用者的移動裝置 (如手機等)：作為與終端節點互動以及控制 gateway 的平台。

![](https://3972650740-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FY4gduUSLWOCI23CXUWej%2Fuploads%2F6aZFjT0QyhqP7wFTck53%2Fscenario.png?alt=media\&token=c5e228ec-9eaa-4b02-afa4-cbf3c2e6f7b1)

{% hint style="info" %}
引用說明

圖示來自 [www.flaticon.com](http://www.flaticon.com/)，作者為 [Freepik](http://www.freepik.com/) 與 [Gregor Cresnar](http://www.flaticon.com/authors/gregor-cresnar)，使用 [CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/) 授權。
{% endhint %}

接下來的章節，將說明上述元件的設置方法；希望藉由這些範例幫助開發者了解其運作機制，並以此為基礎擴充至不同的 IoT 應用場景。

### IoT Gateway - 使用 LinkIt Smart 7688 作為私有雲伺服器及 Wi-Fi repeater <a href="#buildabeaconcontrolledbymcsliteiotgateway-shi-yong-linkitsmart7688-zuo-wei-si-you-yun-si-fu-qi-ji-wi" id="buildabeaconcontrolledbymcsliteiotgateway-shi-yong-linkitsmart7688-zuo-wei-si-you-yun-si-fu-qi-ji-wi"></a>

作為硬體資源比終端節點更強的平台，gateway 主要功能為資料處理與傳輸。LinkIt Smart 7688 在此例中，被設置為 MCS Lite 伺服器，提供私有雲服務處理區網內產生的資料點。此外，LinkIt Smart 7688 並提供 Wi-Fi repeater 功能，使區網內的節點得以連接網際網路。下列兩篇教學文章說明如何將 LinkIt Smart 7688 設置為 MCS Lite 伺服器以及如何使 LinkIt Smart 7688 運作在 Wi-Fi repeater 的中繼模式：

* [將 LinkIt Smart 7688 設置為 MCS Lite 伺服器 (英文)](https://docs.labs.mediatek.com/resource/linkit-smart-7688/en/tutorials/cloud-services/mediatek-cloud-sandbox/setup-linkit-smart-7688-as-a-mcs-lite-server)
* [將 LinkIt Smart 7688 設置為 Wi-Fi repeater 中繼模式 (英文)](https://docs.labs.mediatek.com/resource/linkit-smart-7688/en/tutorials/network/switch-to-repeater-mode)

此外請參閱另一篇[教學文件](https://mcs-lite-introduction.netlify.com/zh-tw/mcs_lite_tutorial/7697_arduino_led_blink.html)，建立可控制 LinkIt 7697 板上 LED 的 MCS Lite 測試裝置，此裝置也會被應用在本文的綜合範例當中。

測試裝置所包含的重要資訊有：

* Device id
* Device key
* 名為 _switch\_display_ 的開/關顯示器通道&#x20;
* 名為 _switch\_controller_ 的開/關控制器通道

當撰寫 LinkIt 7697 的 Arduino sketch 程式碼時，開發者需提供這些資訊至對應的 MCS Lite API 之中。

### IoT 終端節點 - 使用 LinkIt 7697 作為節點裝置與 BLE beacon <a href="#buildabeaconcontrolledbymcsliteiot-zhong-duan-jie-dian-shi-yong-linkit7697-zuo-wei-jie-dian-zhuang-z" id="buildabeaconcontrolledbymcsliteiot-zhong-duan-jie-dian-shi-yong-linkit7697-zuo-wei-jie-dian-zhuang-z"></a>

請先參閱另外兩篇相關主題的教學：

* [使用 MCS Lite 控制 LinkIt 7697 的 LED](https://mcs-lite-introduction.netlify.com/zh-tw/mcs_lite_tutorial/7697_arduino_led_blink.html)
* [將 LinkIt 7697 設置為 Eddystone URL beacon](../../shi-yong-ble-di-gong-hao-lan-ya/lan-ya-xin-biao)

接下來的範例將整合上述文章，將 LinkIt 7697 設置為可受 MCS Lite 控制的 BLE beacon (用來廣播 MCS Lite 控制頁面的 URL)。在此應用下，當使用者裝置 (如已開啟藍芽的手機) 靠近 7697 節點時，會自動收到 MCS Lite 控制頁面的網址資訊，不需為了連結頁面而手動輸入網址。使用的程式碼整合自前述的兩篇教學，主要修改處將會在下列章節說明。若要取得完成的 sketch 程式碼，請參考文末的[參考資料](broken-reference)章節。

#### 設置 AP 連線資訊 <a href="#buildabeaconcontrolledbymcslite-she-zhi-ap-lian-xian-zi-xun" id="buildabeaconcontrolledbymcslite-she-zhi-ap-lian-xian-zi-xun"></a>

程式一開始，開發者需設定 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：

```javascript
WiFi.begin(_SSID);
```

#### 指定 MCS Lite 裝置資訊與 MCS Lite 伺服器的位置 <a href="#buildabeaconcontrolledbymcslite-zhi-ding-mcslite-zhuang-zhi-zi-xun-yu-mcslite-si-fu-qi-de-wei-zhi" id="buildabeaconcontrolledbymcslite-zhi-ding-mcslite-zhuang-zhi-zi-xun-yu-mcslite-si-fu-qi-de-wei-zhi"></a>

欲取得與 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 伺服器](https://cavedu.gitbook.io/cavedu/mcs-lite/mcs-lite-introduction-environment)時所顯示的資訊取得。

#### 定義 MCS Lite 通道資訊 <a href="#buildabeaconcontrolledbymcslite-ding-yi-mcslite-tong-dao-zi-xun" id="buildabeaconcontrolledbymcslite-ding-yi-mcslite-tong-dao-zi-xun"></a>

[建立](https://mcs-lite-introduction.netlify.com/zh-tw/mcs_lite_tutorial/7697_arduino_led_blink.html)這個範例的測試裝置時，會定義顯示器與控制器資料通道。因此在 sketch 裡需指定對應的通道資訊以供伺服器識別：

```
MCSControllerOnOff led("switch_controller"); 
MCSDisplayOnOff remote("switch_display");
```

#### 設置供 BLE 廣播的 Eddystone URL <a href="#buildabeaconcontrolledbymcslite-she-zhi-gong-ble-guang-bo-de-eddystoneurl" id="buildabeaconcontrolledbymcslite-she-zhi-gong-ble-guang-bo-de-eddystoneurl"></a>

為了讓使用者輕易地存取 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**](http://mylinkit.local:3000/)" 需被縮短為 "[**goo.gl/evYXvt**](http://goo.gl/evYXvt)" 後，才符合 Eddystone 的長度規範。關於更多 Eddystone URL 的細節，請參考 7697 Beacon 教學的 "使用 LinkIt 7697 作為 Eddystone-URL Beacon" 章節。

### 使用者平台設定 <a href="#buildabeaconcontrolledbymcslite-shi-yong-zhe-ping-tai-she-ding" id="buildabeaconcontrolledbymcslite-shi-yong-zhe-ping-tai-she-ding"></a>

{% hint style="danger" %}
注意

在進行下列步驟前，請開啟使用者平台的 Wi-Fi 與 BLE 功能，並確認已連接到 IoT gateway。
{% endhint %}

為了識別 Eddystone 廣播資訊，使用者需安裝支援搜尋 Eddystone URL beacon 的應用程式，以下步驟將採用 **Physical Web** 應用程式作為示範。

* [Android 下載連結](https://play.google.com/store/apps/details?id=com.physicalweb\&hl=en\&gl=US)
* [iOS 下載連結](https://itunes.apple.com/app/physical-web/id927653608?mt=8)

安裝後，若在 LinkIt 7697 附近開啟該應用程式，則會看到 beacon 廣播的 URL 如下：

![](https://3972650740-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FY4gduUSLWOCI23CXUWej%2Fuploads%2FJ19cvVMkVPVb0kGvx7P9%2Fpw_7688.png?alt=media\&token=8c7baccf-2811-4cf7-aac6-31539d384852)

除了透過開啟應用程式取得 URL 外，亦支援以 widget 模式讀取 beacon 資訊：

![](https://3972650740-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FY4gduUSLWOCI23CXUWej%2Fuploads%2FigvlTfoSgntxVexmikQn%2Fpw_7688_widget.png?alt=media\&token=659df43f-9d78-441b-9305-59148710f41e)

點選該 URL 即會被導向 URL 所指的 MCS Lite 控制頁面：

![](https://3972650740-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FY4gduUSLWOCI23CXUWej%2Fuploads%2FGO6YN8FhNskuCrugJ5Gd%2Fmcs_lite.png?alt=media\&token=a0ea65c0-8d17-4d16-915f-1acc984000e7)

登入 MCS Lite 服務之後，即可透過手機取得與控制 LinkIt 7697 LED 的狀態：

![](https://3972650740-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FY4gduUSLWOCI23CXUWej%2Fuploads%2F9Wdyt1WZbJYHi1BAuz11%2Fcontrol_pannel.png?alt=media\&token=b950578a-3491-4a99-947f-7e34a4b0ffa9)

### 參考資料 <a href="#buildabeaconcontrolledbymcslite-can-kao-zi-liao-appendix" id="buildabeaconcontrolledbymcslite-can-kao-zi-liao-appendix"></a>

以下為 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 !!");
  }
}
```
