本文檔介紹驅動(設備接入模塊)的Connector架構模式。Connector是一種結構清晰又靈活的模式,方便您快速構建驅動。我們推薦您使用Connector架構模式構建驅動程序。
Connector架構模式目前只適用于Node.js和Python的設備接入SDK。
概述
- ThingAccessClient
此類由設備接入SDK提供,提供多個方法與Link IoT Edge交互,包括數據上行和數據下行。同時接受外部傳入ThingAccessClientCallbacks類型回調函數,在收到Link IoT Edge的下行數據時調用回調接口。Connector架構中ThingAccessClientCallbacks的實現類是Connector類。
- Connector
Connector架構核心組件。對外,Connector組件提供connect和disconnect接口,并接受外部注入Thing接口。對內,Connector組件實現ThingAccessClientCallbacks接口,并在構建ThingAccessClient對象時傳入,以建立與Link IoT Edge的連接,并在收到回調指令時轉發指令到設備。
- Thing
對物理設備接口提供封裝,負責與設備交互,方便Connector組件調用,對外提供面向對象的API。Thing在這里只是一個統稱,接入具體設備時為具體設備抽象類,如Light(表示燈設備)。
- Entry
驅動程序主入口,將會獲取驅動配置,初始Thing組件和Connector組件,最終調用Connector組件的connect方法連接設備和Link IoT Edge。也可調用disconnect方法斷開設備與Link IoT Edge的連接。
Connector組件是Connector架構中最重要的組件,它通過組合的方式將設備抽象接口(Thing)和Link IoT Edge抽象接口(ThingAccessClient)關聯起來,因此而得名Connector。
UML類圖如下所示:
操作步驟
下文示例使用Node.js版本設備接入SDK實現Connector架構模式。關于Python版本示例及詳細信息可參考Python版本。
Light
- 抽象模擬燈類。通過設置isOn屬性的true和false來標識模擬燈的開和關。
示例代碼如下:
/** * A virtual light which can be turned on or off by updating its * <code>isOn</code> property. */ class Light { constructor() { this._isOn = true; } get isOn() { return this._isOn; } set isOn(value) { return this._isOn = value; }
- 實現Connector。代碼主要包含如下功能:
- 構造函數接收設備的配置參數和設備抽象對象,內部構造ThingAccessClient以便與Link IoT Edge交互。
- 實現ThingAccessClientCallbacks的3個回調方法,并在回調方法中調用設備對象接口與設備交互。
- 提供connect方法和disconnect方法。其中在connect方法里連接Link IoT Edge,在disconnect方法里斷開設備與Link IoT Edge的連接。
示例代碼如下:
/** * The class combines ThingAccessClient and the thing that connects * to Link IoT Edge. */ class Connector { constructor(config, light) { this.config = config; this.light = light; this._client = new ThingAccessClient(config, { setProperties: this._setProperties.bind(this), getProperties: this._getProperties.bind(this), callService: this._callService.bind(this), }); } /** * Connects to Link IoT Edge and publishes properties to it. */ connect() { registerAndOnlineWithBackOffRetry(this._client, 1) .then(() => { return new Promise(() => { // Publish properties to Link IoT Edge platform. const properties = { 'LightSwitch': this.light.isOn ? 1 : 0 }; this._client.reportProperties(properties); }); }) .catch(err => { console.log(err); return this._client.cleanup(); }) .catch(err => { console.log(err); }); } /** * Disconnects from Link IoT Edge and stops publishing properties to it. */ disconnect() { this._client.cleanup() .catch(err => { console.log(err); }); } _setProperties(properties) { console.log('Set properties %s to thing %s-%s', JSON.stringify(properties), this.config.productKey, this.config.deviceName); if ('LightSwitch' in properties) { var value = properties['LightSwitch']; var isOn = value === 1; if (this.light.isOn !== isOn) { // Report new property to Link IoT Edge if it changed. this.light.isOn = isOn; if (this._client) { properties = {'LightSwitch': value}; console.log(`Report properties: ${JSON.stringify(properties)}`); this._client.reportProperties(properties); } } return { code: RESULT_SUCCESS, message: 'success', }; } return { code: RESULT_FAILURE, message: 'The requested properties does not exist.', }; } _getProperties(keys) { console.log('Get properties %s from thing %s-%s', JSON.stringify(keys), this.config.productKey, this.config.deviceName); if (keys.includes('LightSwitch')) { return { code: RESULT_SUCCESS, message: 'success', params: { 'LightSwitch': this.light.isOn ? 1 : 0, } }; } return { code: RESULT_FAILURE, message: 'The requested properties does not exist.', } } _callService(name, args) { console.log('Call service %s with %s on thing %s-%s', JSON.stringify(name), JSON.stringify(args), this.config.productKey, this.config.deviceName); return { code: RESULT_FAILURE, message: 'The requested service does not exist.', }; } }
- 獲取配置信息,并初始化Connector架構組件。
- 調用getConfig獲取驅動配置。
- 調用getThingInfos獲取設備信息及配置。
- 初始化Connector組件。
- 調用connect連接Link IoT Edge。
示例代碼如下:
// Get the config which is auto-generated when devices are bound to this driver. getConfig() .then((config) => { // Get the device information from config, which contains product key, device // name, etc. of the device. const thingInfos = config.getThingInfos(); thingInfos.forEach((thingInfo) => { const light = new Light(); // The ThingInfo format is just right for connector config, pass it directly. const connector = new Connector(thingInfo, light); connector.connect(); }); });
LightSensor
- 抽象模擬光照度傳感器類。此處模擬光照度傳感器有外部監聽時會自動運行,在重置外部監聽后會停止運行。
示例代碼如下:
/** * A virtual light sensor which starts to publish illuminance between 100 * and 600 with 100 delta changes once someone listen to it. */ class LightSensor { constructor() { this._illuminance = 200; this._delta = 100; } get illuminance() { return this._illuminance; } // Start to work. start() { if (this._clearInterval) { this._clearInterval(); } console.log('Starting light sensor...'); const timeout = setInterval(() => { // Update illuminance and delta. let delta = this._delta; let illuminance = this._illuminance; if (illuminance >= 600 || illuminance <= 100) { delta = -delta; } illuminance += delta; this._delta = delta; this._illuminance = illuminance; if (this._listener) { this._listener({ properties: { illuminance, } }); } }, 2000); this._clearInterval = () => { clearInterval(timeout); this._clearInterval = undefined; }; return this._clearInterval; } stop() { console.log('Stopping light sensor ...'); if (this._clearInterval) { this._clearInterval(); } } listen(callback) { if (callback) { this._listener = callback; // Start to work when some one listen to this. this.start(); } else { this._listener = undefined; this.stop(); } } }
- 實現Connector。
- 構造函數接收設備的配置參數和設備抽象對象,內部構造ThingAccessClient以便與Link IoT Edge交互。
- 實現ThingAccessClientCallbacks的3個回調方法,并在回調方法中調用設備對象接口與設備交互。
- 提供connect方法和disconnect方法。其中在connect方法里連接Link IoT Edge,在disconnect方法里斷開設備與Link IoT Edge的連接。
示例代碼如下:
/** * The class combines ThingAccessClient and the thing that connects to Link IoT Edge. */ class Connector { constructor(config, lightSensor) { this.config = config; this.lightSensor = lightSensor; this._client = new ThingAccessClient(config, { setProperties: this._setProperties.bind(this), getProperties: this._getProperties.bind(this), callService: this._callService.bind(this), }); } /** * Connects to Link IoT Edge and publishes properties to it. */ connect() { registerAndOnlineWithBackOffRetry(this._client, 1) .then(() => { return new Promise(() => { // Running..., listen to sensor, and report to Link IoT Edge. this.lightSensor.listen((data) => { const properties = {'MeasuredIlluminance': data.properties.illuminance}; console.log(`Report properties: ${JSON.stringify(properties)}`); this._client.reportProperties(properties); }); }); }) .catch(err => { console.log(err); return this._client.cleanup(); }) .catch(err => { console.log(err); }); } /** * Disconnects from Link IoT Edge. */ disconnect() { // Clean the listener. this.lightSensor.listen(undefined); this._client.cleanup() .catch(err => { console.log(err); }); } _setProperties(properties) { console.log('Set properties %s to thing %s-%s', JSON.stringify(properties), this.config.productKey, this.config.deviceName); return { code: RESULT_FAILURE, message: 'The property is read-only.', }; } _getProperties(keys) { console.log('Get properties %s from thing %s-%s', JSON.stringify(keys), this.config.productKey, this.config.deviceName); if (keys.includes('MeasuredIlluminance')) { return { code: RESULT_SUCCESS, message: 'success', params: { 'MeasuredIlluminance': this.lightSensor.illuminance, } }; } return { code: RESULT_FAILURE, message: 'The requested properties does not exist.', } } _callService(name, args) { console.log('Call service %s with %s on thing %s-%s', JSON.stringify(name), JSON.stringify(args), this.config.productKey, this.config.deviceName); return { code: RESULT_FAILURE, message: 'The requested service does not exist.', }; } }
- 獲取配置信息,并初始化Connector架構組件。
- 調用getConfig獲取驅動配置。
- 調用getThingInfos獲取設備信息及配置。
- 初始化Connector組件。
- 調用connect連接Link IoT Edge。
示例代碼如下:
// Get the config which is auto-generated when devices are bound to this driver. getConfig() .then((config) => { // Get the device information from config, which contains product key, device // name, etc. of the device. const thingInfos = config.getThingInfos(); thingInfos.forEach((thingInfo) => { const lightSensor = new LightSensor(); // The ThingInfo format is just right for connector config, pass it directly. const connector = new Connector(thingInfo, lightSensor); connector.connect(); }); });