排程及廣播作業 (Node.js)
使用 Azure IoT 中樞排程和追蹤會更新數百萬部裝置的作業。 使用作業以:
- 更新所需屬性
- 更新標籤
- 叫用直接方法
就概念而言,作業會包裝上述其中一個動作,然後針對由裝置對應項 (twin) 查詢所定義的一組裝置,追蹤執行進度。 例如,後端應用程式可以在 10,000 個裝置上使用作業叫用重新啟動方法,此方法由裝置對應項查詢指定並排定在未來執行。 接著,該應用程式可以追蹤每個這些裝置接收和執行重新啟動方法的進度。
從下列文章深入了解這當中的每一項功能:
裝置對應項和屬性:開始使用裝置對應項和了解並使用 IoT 中樞中的裝置對應項屬性
直接方法:IoT 中樞開發人員指南 - 直接方法 (部分機器翻譯)
注意
本文中所述的功能僅適用於 IoT 中樞的標準層。 如需基本和標準/免費 IoT 中樞層的詳細資訊,請參閱選擇適合您解決方案的 IoT 中樞層 (部分機器翻譯)。
本文說明如何建立兩個 Node.js 應用程式:
Node.js 模擬裝置應用程式 simDevice.js,其實作 lockDoor 直接方法,後端應用程式可呼叫此方法。
Node.js 主控台應用程式 scheduleJobService.js,其會建立兩個作業。 一個作業會呼叫 lockDoor 直接方法,而另一個作業會將所需的屬性更新傳送至多個裝置。
注意
如需可用來建置裝置和後端應用程式的 SDK 工具詳細資訊,請參閱 Azure IoT SDK。
必要條件
Azure 訂用帳戶中的 IoT 中樞。 如果您還沒有中樞,可遵循建立 IoT 中樞中的步驟。
在 IoT 中樞內註冊的裝置。 如果 IoT 中樞中沒有裝置,請遵循註冊裝置中的步驟。
Node.js 10.0.x 版或更新版本。 準備開發環境說明如何在 Windows 或 Linux 上安裝本文的 Node.js。
請確定您的防火牆已開啟連接埠 8883。 本文中的裝置範例會使用 MQTT 通訊協定,其會透過連接埠 8883 進行通訊。 某些公司和教育網路環境可能會封鎖此連接埠。 如需此問題的詳細資訊和解決方法,請參閱連線至 IoT 中樞 (MQTT)。
建立模擬裝置應用程式
在本節中,您建立 Node.js 主控台應用程式,回應雲端所呼叫的直接方法,可觸發模擬的 lockDoor 方法。
重要
本文包含使用共用存取簽章 (也稱為對稱金鑰驗證) 連線裝置的步驟。 此驗證方法方便進行測試和評估,但使用 X.509 憑證來驗證裝置是更安全的方法。 若要深入了解,請參閱安全性最佳做法>連線安全性。
建立名為 simDevice 的新空白資料夾。 在命令提示字元中,使用下列命令在 simDevice 資料夾中建立 package.json 檔案。 接受所有預設值:
npm init
在命令提示字元中,於 simDevice 資料夾中執行下列命令來安裝 azure-iot-device 裝置 SDK 套件和 azure-iot-device-mqtt 套件:
npm install azure-iot-device azure-iot-device-mqtt --save
使用文字編輯器,在 [simDevice] 資料夾中建立新的 simDevice.js 檔案。
在 simDevice.js 檔案的開頭新增下列 'require' 陳述式:
'use strict'; var Client = require('azure-iot-device').Client; var Protocol = require('azure-iot-device-mqtt').Mqtt;
新增 connectionString 變數,並用它來建立用戶端執行個體。 將
{yourDeviceConnectionString}
預留位置值由您先前所複製的裝置連接字串取代。var connectionString = '{yourDeviceConnectionString}'; var client = Client.fromConnectionString(connectionString, Protocol);
新增下列函式以處理 lockDoor 方法。
var onLockDoor = function(request, response) { // Respond the cloud app for the direct method response.send(200, function(err) { if (err) { console.error('An error occurred when sending a method response:\n' + err.toString()); } else { console.log('Response to method \'' + request.methodName + '\' sent successfully.'); } }); console.log('Locking Door!'); };
新增下列程式碼以註冊 lockDoor 方法的處理常式。
client.open(function(err) { if (err) { console.error('Could not connect to IotHub client.'); } else { console.log('Client connected to IoT Hub. Register handler for lockDoor direct method.'); client.onDeviceMethod('lockDoor', onLockDoor); } });
儲存並關閉 simDevice.js 檔案。
注意
為了簡單起見,本文章不會實作重試原則。 在生產環境程式碼中,您應該如暫時性錯誤處理一文中所建議,實作重試原則 (例如指數型輪詢)。
取得 IoT 中樞連接字串
在本文中,您會建立後端服務,其會排程在裝置上叫用直接方法的作業、排程更新裝置對應項的作業,以及監視每項作業的進度。 若要執行這些作業,則服務需要有登錄讀取和登錄寫入權限。 根據預設,每個 IoT 中樞都是使用授與這些權限且名為 registryReadWrite 的共用存取原則所建立。
若要取得 registryReadWrite 原則的 IoT 中樞連接字串,請遵循下列步驟:
在 Azure 入口網站中,選取 [資源群組]。 選取中樞所在的資源群組,然後從資源清單選取中樞。
在中樞的左側窗格中,選取 [共用存取原則]。
從原則清單中,選取 registryReadWrite 原則。
複製 [主要連接字串] 並儲存該值。
如需 IoT 中樞共用存取原則和權限的詳細資訊,請參閱存取控制及權限。
重要
本文包含使用共用存取簽章連線至服務的步驟。 此驗證方法方便進行測試和評估,但使用 Microsoft Entra ID 或受控識別向服務進行驗證是更安全的方法。 若要深入了解,請參閱安全性最佳做法 > 雲端安全性。
排定用於呼叫直接方法及更新裝置對應項 (twin) 屬性的作業
在本節中,您會建立一個 Node.js 主控台 App,此 App 會使用直接方法在裝置上初始化遠端 lockDoor,並更新裝置對應項 (twin) 的屬性。
建立名為 scheduleJobService 的新空白資料夾。 在命令提示字元中,使用下列命令在 scheduleJobService 資料夾中建立 package.json 檔案。 接受所有預設值:
npm init
在命令提示字元中,於 scheduleJobService 資料夾中執行下列命令來安裝 azure-iothub 裝置 SDK 套件和 azure-iot-device-mqtt 套件:
npm install azure-iothub uuid --save
使用文字編輯器,在 [scheduleJobService] 資料夾中建立新的 scheduleJobService.js 檔案。
在 scheduleJobService.js 檔案的開頭新增下列「要求」陳述式:
'use strict'; var uuid = require('uuid'); var JobClient = require('azure-iothub').JobClient;
新增下列變數宣告。 將
{iothubconnectionstring}
預留位置值由先前在取得 IoT 中樞連接字串內複製的值取代。 如果您註冊的裝置與 myDeviceId 不同,請務必在查詢條件中加以變更。var connectionString = '{iothubconnectionstring}'; var queryCondition = "deviceId IN ['myDeviceId']"; var startTime = new Date(); var maxExecutionTimeInSeconds = 300; var jobClient = JobClient.fromConnectionString(connectionString);
新增下列將用來監視作業執行的函式:
function monitorJob (jobId, callback) { var jobMonitorInterval = setInterval(function() { jobClient.getJob(jobId, function(err, result) { if (err) { console.error('Could not get job status: ' + err.message); } else { console.log('Job: ' + jobId + ' - status: ' + result.status); if (result.status === 'completed' || result.status === 'failed' || result.status === 'cancelled') { clearInterval(jobMonitorInterval); callback(null, result); } } }); }, 5000); }
新增下列程式碼來排定呼叫裝置方法的作業:
var methodParams = { methodName: 'lockDoor', payload: null, responseTimeoutInSeconds: 15 // Timeout after 15 seconds if device is unable to process method }; var methodJobId = uuid.v4(); console.log('scheduling Device Method job with id: ' + methodJobId); jobClient.scheduleDeviceMethod(methodJobId, queryCondition, methodParams, startTime, maxExecutionTimeInSeconds, function(err) { if (err) { console.error('Could not schedule device method job: ' + err.message); } else { monitorJob(methodJobId, function(err, result) { if (err) { console.error('Could not monitor device method job: ' + err.message); } else { console.log(JSON.stringify(result, null, 2)); } }); } });
新增下列程式碼來排定更新裝置對應項 (twin) 的作業:
var twinPatch = { etag: '*', properties: { desired: { building: '43', floor: 3 } } }; var twinJobId = uuid.v4(); console.log('scheduling Twin Update job with id: ' + twinJobId); jobClient.scheduleTwinUpdate(twinJobId, queryCondition, twinPatch, startTime, maxExecutionTimeInSeconds, function(err) { if (err) { console.error('Could not schedule twin update job: ' + err.message); } else { monitorJob(twinJobId, function(err, result) { if (err) { console.error('Could not monitor twin update job: ' + err.message); } else { console.log(JSON.stringify(result, null, 2)); } }); } });
儲存並關閉 scheduleJobService.js 檔案。
執行應用程式
現在您已經準備好執行應用程式。
在命令提示字元中,於 simDevice 資料夾中執行下列命令來開始接聽重新啟動直接方法。
node simDevice.js
在 scheduleJobService 資料夾的命令提示字元中,執行下列命令以觸發鎖門作業並更新對應項
node scheduleJobService.js
您會在主控台中看到裝置對直接方法的回應和工作狀態。
下列顯示裝置對直接方法的回應:
以下顯示對直接方法和裝置對應項更新的服務排程作業,以及執行至完成的作業:
下一步
在本文中,您已排程工作來執行直接方法,並更新裝置對應項的屬性。
若要繼續探索 IoT 中樞和裝置管理模式,請更新使用 Raspberry Pi 3 B+ 參考映像的 Azure IoT 中樞裝置更新教學課程中的映像。