跳至主要内容

將您的應用程式邏輯遷移到雲端

本課程的手繪筆記概述

手繪筆記由 Nitya Narasimhan 提供。點擊圖片查看大圖。

本課程是 IoT 01 for Beginners Project 2 - Digital Agriculture series 的一部分,由 Microsoft Reactor 教授。

使用無伺服器代碼控制您的 IoT 設備

課前測驗

課前測驗

簡介

在上一課中,您學會了如何將植物土壤濕度監測和繼電器控制連接到基於雲端的 IoT 服務。下一步是將控制繼電器定時的伺服器代碼移動到雲端。在本課中,您將學習如何使用無伺服器函數來完成此操作。

在本課中,我們將涵蓋:

什麼是無伺服器?

無伺服器,或無伺服器計算,涉及創建在雲端運行的小代碼塊,以響應不同類型的事件。當事件發生時,您的代碼會運行,並且會傳遞有關事件的數據。這些事件可以來自許多不同的事物,包括網絡請求、放置在隊列中的消息、數據庫中的數據變更或 IoT 設備發送到 IoT 服務的消息。

事件從 IoT 服務發送到無伺服器服務,所有事件同時由多個運行的函數處理

💁 如果您以前使用過數據庫觸發器,您可以將其視為相同的東西,代碼由插入行等事件觸發。

當許多事件同時發送時,無伺服器服務會擴展以同時運行所有事件

您的代碼僅在事件發生時運行,其他時間不會保持您的代碼處於活動狀態。事件發生時,您的代碼會被加載並運行。這使得無伺服器非常可擴展 - 如果許多事件同時發生,雲提供商可以同時運行您的函數多次,跨越他們可用的任何伺服器。這樣的缺點是,如果您需要在事件之間共享信息,您需要將其保存在某個地方,例如數據庫,而不是存儲在內存中。

您的代碼被寫成一個函數,該函數將有關事件的詳細信息作為參數。您可以使用多種編程語言來編寫這些無伺服器函數。

🎓 無伺服器也被稱為函數即服務 (FaaS),因為每個事件觸發器都在代碼中實現為一個函數。

儘管名稱如此,無伺服器實際上確實使用伺服器。這個名稱是因為作為開發人員的您不需要關心運行代碼所需的伺服器,您只需要關心代碼是否響應事件而運行。雲提供商有一個無伺服器運行時,負責管理分配伺服器、網絡、存儲、CPU、內存和運行代碼所需的所有其他資源。這種模式意味著您不能按伺服器付費,因為沒有伺服器。相反,您按代碼運行的時間和使用的內存量付費。

💰 無伺服器是雲端運行代碼的最便宜方式之一。例如,在撰寫本文時,一個雲提供商允許您的所有無伺服器函數每月執行總共 1,000,000 次,然後才開始向您收費,之後每 1,000,000 次執行收費 0.20 美元。當您的代碼不運行時,您不需要付費。

作為 IoT 開發人員,無伺服器模型是理想的。您可以編寫一個函數,該函數會響應從連接到您的雲託管 IoT 服務的任何 IoT 設備發送的消息。您的代碼將處理所有發送的消息,但僅在需要時運行。

✅ 回顧您編寫的作為伺服器代碼監聽 MQTT 消息的代碼。這如何在雲端使用無伺服器運行?您認為代碼需要如何更改以支持無伺服器計算?

💁 無伺服器模型正在移動到其他雲服務,除了運行代碼。例如,雲中提供無伺服器定價模型的無伺服器數據庫,您按對數據庫的每次請求付費,例如查詢或插入,通常基於完成請求所需的工作量定價。例如,針對主鍵選擇一行的單個選擇將比聯接多個表並返回數千行的複雜操作花費更少。

創建無伺服器應用程式

Microsoft 的無伺服器計算服務稱為 Azure Functions。

Azure Functions 標誌

下面的短視頻概述了 Azure Functions

Azure Functions 概述視頻

🎥 點擊上面的圖片觀看視頻

✅ 花點時間進行一些研究,閱讀 Microsoft Azure Functions 文檔 中的 Azure Functions 概述。

要編寫 Azure Functions,您需要使用您選擇的語言創建一個 Azure Functions 應用程式。開箱即用的 Azure Functions 支持 Python、JavaScript、TypeScript、C#、F#、Java 和 Powershell。在本課中,您將學習如何使用 Python 編寫 Azure Functions 應用程式。

💁 Azure Functions 還支持自定義處理程序,因此您可以使用任何支持 HTTP 請求的語言編寫函數,包括較舊的語言如 COBOL。

函數應用程式由一個或多個觸發器組成 - 響應事件的函數。您可以在一個函數應用程式中擁有多個觸發器,所有觸發器共享共同的配置。例如,在您的函數應用程式的配置文件中,您可以擁有 IoT 中樞的連接詳細信息,應用程式中的所有函數都可以使用這些詳細信息進行連接並監聽事件。

任務 - 安裝 Azure Functions 工具

在撰寫本文時,Azure Functions 代碼工具在 Apple Silicon 上與 Python 項目不完全兼容。您需要使用基於 Intel 的 Mac、Windows PC 或 Linux PC。

Azure Functions 的一個很棒的功能是您可以在本地運行它們。雲中使用的相同運行時可以在您的計算機上運行,允許您編寫響應 IoT 消息的代碼並在本地運行它。您甚至可以在處理事件時調試代碼。一旦您對代碼感到滿意,就可以將其部署到雲端。

Azure Functions 工具可作為 CLI 使用,稱為 Azure Functions Core Tools。

  1. 按照 Azure Functions Core Tools 文檔 中的說明安裝 Azure Functions 核心工具

  2. 安裝 VS Code 的 Azure Functions 擴展。此擴展提供創建、調試和部署 Azure 函數的支持。請參閱 Azure Functions 擴展文檔 了解在 VS Code 中安裝此擴展的說明。

當您將 Azure Functions 應用程式部署到雲端時,它需要使用少量雲存儲來存儲應用程式文件和日誌文件等內容。當您在本地運行函數應用程式時,您仍然需要連接到雲存儲,但可以使用名為 Azurite 的存儲模擬器,而不是使用實際的雲存儲。這在本地運行,但表現得像雲存儲。

🎓 在 Azure 中,Azure Functions 使用的存儲是一個 Azure 存儲帳戶。這些帳戶可以存儲文件、Blob、表中的數據或隊列中的數據。您可以在多個應用程式之間共享一個存儲帳戶,例如函數應用程式和 Web 應用程式。

  1. Azurite 是一個 Node.js 應用程式,因此您需要安裝 Node.js。您可以在 Node.js 網站 上找到下載和安裝說明。如果您使用的是 Mac,您也可以從 Homebrew 安裝它。

  2. 使用以下命令安裝 Azurite(npm 是安裝 Node.js 時安裝的工具):

    npm install -g azurite
  3. 創建一個名為 azurite 的文件夾供 Azurite 用於存儲數據:

    mkdir azurite
  4. 運行 Azurite,將此新文件夾傳遞給它:

    azurite --location azurite

    Azurite 存儲模擬器將啟動並準備好連接本地函數運行時。

    ➜  ~ azurite --location azurite  
    Azurite Blob service is starting at http://127.0.0.1:10000
    Azurite Blob service is successfully listening at http://127.0.0.1:10000
    Azurite Queue service is starting at http://127.0.0.1:10001
    Azurite Queue service is successfully listening at http://127.0.0.1:10001
    Azurite Table service is starting at http://127.0.0.1:10002
    Azurite Table service is successfully listening at http://127.0.0.1:10002

任務 - 創建 Azure Functions 項目

Azure Functions CLI 可用於創建新的函數應用程式。

  1. 為您的函數應用程式創建一個文件夾並導航到該文件夾。將其命名為 soil-moisture-trigger

    mkdir soil-moisture-trigger
    cd soil-moisture-trigger
  2. 在此文件夾中創建一個 Python 虛擬環境:

    python3 -m venv .venv
  3. 激活虛擬環境:

    • 在 Windows 上:

      • 如果您使用的是命令提示符或 Windows 終端中的命令提示符,請運行:

        .venv\Scripts\activate.bat
      • 如果您使用的是 PowerShell,請運行:

        .\.venv\Scripts\Activate.ps1
    • 在 macOS 或 Linux 上,運行:

      source ./.venv/bin/activate

    💁 這些命令應該從您運行創建虛擬環境命令的相同位置運行。您永遠不需要導航到 .venv 文件夾,您應該始終從創建虛擬環境時所在的文件夾運行激活命令和任何安裝包或運行代碼的命令。

  4. 運行以下命令在此文件夾中創建一個函數應用程式:

    func init --worker-runtime python soil-moisture-trigger

    這將在當前文件夾中創建三個文件:

    • host.json - 這個 JSON 文檔包含您的函數應用程式的設置。您不需要修改這些設置。
    • local.settings.json - 這個 JSON 文檔包含您的應用程式在本地運行時使用的設置,例如 IoT 中樞的連接字符串。這些設置僅限於本地,不應添加到源代碼控制中。當您將應用程式部署到雲端時,這些設置不會被部署,而是從應用程式設置中加載。這將在本課後面介紹。
    • requirements.txt - 這是一個 Pip requirements 文件,包含運行您的函數應用程式所需的 Pip 包。
  5. local.settings.json 文件有一個設置,用於函數應用程式將使用的存儲帳戶。默認為空設置,因此需要設置。要連接到本地存儲模擬器 Azurite,將此值設置為以下內容:

    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
  6. 使用 requirements 文件安裝必要的 Pip 包:

    pip install -r requirements.txt

    💁 必需的 Pip 包需要在此文件中,以便當函數應用程式部署到雲端時,運行時可以確保安裝正確的包。

  7. 為了測試一切是否正常工作,您可以啟動函數運行時。運行以下命令來啟動它:

    func start

    您將看到運行時啟動並報告未找到任何作業函數(觸發器)。

    (.venv) ➜  soil-moisture-trigger func start
    Found Python version 3.9.1 (python3).

    Azure Functions Core Tools
    Core Tools Version: 3.0.3442 Commit hash: 6bfab24b2743f8421475d996402c398d2fe4a9e0 (64-bit)
    Function Runtime Version: 3.0.15417.0

    [2021-05-05T01:24:46.795Z] No job functions found.

    ⚠️ 如果您收到防火牆通知,請授予訪問權限,因為 func 應用程式需要能夠讀寫您的網絡。

    ⚠️ 如果您使用的是 macOS,輸出中可能會有警告:

    (.venv) ➜  soil-moisture-trigger func start
    Found Python version 3.9.1 (python3).

    Azure Functions Core Tools
    Core Tools Version: 3.0.3442 Commit hash: 6bfab24b2743f8421475d996402c398d2fe4a9e0 (64-bit)
    Function Runtime Version: 3.0.15417.0

    [2021-06-16T08:18:28.315Z] Cannot create directory for shared memory usage: /dev/shm/AzureFunctions
    [2021-06-16T08:18:28.316Z] System.IO.FileSystem: Access to the path '/dev/shm/AzureFunctions' is denied. Operation not permitted.
    [2021-06-16T08:18:30.361Z] No job functions found.

    只要函數應用程式啟動並正確列出運行的函數,您就可以忽略這些警告。如 Microsoft Docs Q&A 中的這個問題 所述,可以忽略它們。

  8. ctrl+c 停止函數應用程式。

  9. 在 VS Code 中打開當前文件夾,無論是通過打開 VS Code 然後打開此文件夾,還是運行以下命令:

    code .

    VS Code 將檢測到您的函數項目並顯示一個通知,說明:

    檢測到文件夾 "soil-moisture-trigger" 中的 Azure Functions 項目,可能是在 VS Code 之外創建的。初始化以便在 VS Code 中最佳使用?

    通知

    從此通知中選擇

  10. 確保 Python 虛擬環境在 VS Code 終端中運行。如有必要,終止並重新啟動它。

創建 IoT 中樞事件觸發器

函數應用程式是您的無伺服器代碼的外殼。要響應 IoT 中樞事件,您可以向此應用程式添加一個 IoT 中樞觸發器。此觸發器需要連接到發送到 IoT 中樞的消息流並響應它們。要獲取此消息流,您的觸發器需要連接到 IoT 中樞的事件中樞兼容端點

IoT 中樞基於另一個 Azure 服務 Azure 事件中樞。事件中樞是一個允許您發送和接收消息的服務,IoT 中樞擴展了這一點,增加了 IoT 設備的功能。連接以從 IoT 中樞讀取消息的方式與使用事件中樞的方式相同。

✅ 進行一些研究:閱讀 Azure 事件中樞文檔 中的事件中樞概述。基本功能與 IoT 中樞相比如何?

要連接到 IoT 中樞的 IoT 設備,必須使用一個秘密密鑰,以確保只有允許的設備可以連接。連接以讀取消息時也是如此,您的代碼需要一個包含秘密密鑰的連接字符串,以及 IoT 中樞的詳細信息。

💁 您獲取的默認連接字符串具有 iothubowner 權限,這使得使用它的任何代碼都具有 IoT 中樞的完全權限。理想情況下,您應該使用最低級別的權限進行連接。這將在下一課中介紹。

一旦您的觸發器連接,函數內的代碼將對 IoT 中樞發送的每條消息進行調用,無論是哪個設備發送的。觸發器將消息作為參數傳遞。

任務 - 獲取事件中樞兼容端點連接字符串

  1. 從 VS Code 終端運行以下命令以獲取 IoT 中樞事件中樞兼容端點的連接字符串:

    az iot hub connection-string show --default-eventhub \
    --output table \
    --hub-name <hub_name>

    <hub_name> 替換為您用於 IoT 中樞的名稱。

  2. 在 VS Code 中打開 local.settings.json 文件。在 Values 部分內添加以下附加值:

    "IOT_HUB_CONNECTION_STRING": "<connection string>"

    <connection string> 替換為上一步中的值。您需要在上面的行後添加逗號以使其成為有效的 JSON。

任務 - 創建事件觸發器

您現在可以創建事件觸發器了。

  1. 從 VS Code 終端運行以下命令,從 soil-moisture-trigger 文件夾內運行:

    func new --name iot-hub-trigger --template "Azure Event Hub trigger"

    這將創建一個名為 iot-hub-trigger 的新函數。觸發器將連接到 IoT 中樞的事件中樞兼容端點,因此您可以使用事件中樞觸發器。沒有特定的 IoT 中樞觸發器。

這將在 soil-moisture-trigger 文件夾內創建一個名為 iot-hub-trigger 的文件夾,其中包含此函數。此文件夾內將包含以下文件:

  • __init__.py - 這是包含觸發器的 Python 代碼文件,使用標準的 Python 文件名約定將此文件夾轉換為 Python 模塊。

    此文件將包含以下代碼:

    import logging

    import azure.functions as func


    def main(event: func.EventHubEvent):
    logging.info('Python EventHub trigger processed an event: %s',
    event.get_body().decode('utf-8'))

    觸發器的核心是 main 函數。每當 IoT 中樞發送消息時,這個函數就會被調用,將該消息作為 event 傳遞,並附帶與上一課中看到的註釋相同的屬性。

    函數的核心是記錄事件。

  • function.json - 這包含觸發器的配置。主要配置在名為 bindings 的部分中。綁定是 Azure Functions 與其他 Azure 服務之間連接的術語。此函數具有輸入綁定到事件中樞 - 它連接到事件中樞並接收數據。

    💁 您還可以有輸出綁定,以便函數的輸出發送到另一個服務。例如,您可以添加一個輸出綁定到數據庫並返回 IoT 中樞事件,並且它將自動插入到數據庫中。

    ✅ 進行一些研究:閱讀 Azure Functions 觸發器和綁定概念文檔 中的綁定。

    bindings 部分包括綁定的配置。感興趣的值是:

    • "type": "eventHubTrigger" - 這告訴函數它需要監聽來自事件中樞的事件

    • "name": "events" - 這是用於事件中樞事件的參數名稱。這與 Python 代碼中 main 函數中的參數名稱匹配。

    • "direction": "in" - 這是一個輸入綁定,來自事件中樞的數據進入函數

    • "connection": "" - 這定義了讀取連接字符串的設置名稱。在本地運行時,這將從 local.settings.json 文件中讀取此設置。

      💁 連接字符串不能存儲在 function.json 文件中,必須從設置中讀取。這是為了防止您意外暴露連接字符串。

  1. 由於 Azure Functions 模板中的錯誤function.json 中的 cardinality 字段值不正確。將此字段從 many 更新為 one

    "cardinality": "one",
  2. 更新 function.json 文件中 "connection" 的值,以指向您在 local.settings.json 文件中添加的新值:

    "connection": "IOT_HUB_CONNECTION_STRING",

    💁 記住 - 這需要指向設置,而不是包含實際的連接字符串。

  3. 連接字符串包含 eventHubName 值,因此 function.json 文件中的此值需要清空。將此值更新為空字符串:

    "eventHubName": "",

任務 - 運行事件觸發器

  1. 確保您未運行 IoT 中樞事件監視器。如果這與函數應用程式同時運行,函數應用程式將無法連接並消耗事件。

    💁 多個應用程式可以使用不同的消費者組連接到 IoT 中樞端點。這些將在後面的課程中介紹。

  2. 要運行函數應用程式,請從 VS Code 終端運行以下命令

    func start

    函數應用程式將啟動,並將發現 iot-hub-trigger 函數。然後它將處理過去一天內發送到 IoT 中樞的任何事件。

    (.venv) ➜  soil-moisture-trigger func start
    Found Python version 3.9.1 (python3).

    Azure Functions Core Tools
    Core Tools Version: 3.0.3442 Commit hash: 6bfab24b2743f8421475d996402c398d2fe4a9e0 (64-bit)
    Function Runtime Version: 3.0.15417.0

    Functions:

    iot-hub-trigger: eventHubTrigger

    For detailed output, run func with --verbose flag.
    [2021-05-05T02:44:07.517Z] Worker process started and initialized.
    [2021-05-05T02:44:09.202Z] Executing 'Functions.iot-hub-trigger' (Reason='(null)', Id=802803a5-eae9-4401-a1f4-176631456ce4)
    [2021-05-05T02:44:09.205Z] Trigger Details: PartitionId: 0, Offset: 1011240-1011632, EnqueueTimeUtc: 2021-05-04T19:04:04.2030000Z-2021-05-04T19:04:04.3900000Z, SequenceNumber: 2546-2547, Count: 2
    [2021-05-05T02:44:09.352Z] Python EventHub trigger processed an event: {"soil_moisture":628}
    [2021-05-05T02:44:09.354Z] Python EventHub trigger processed an event: {"soil_moisture":624}
    [2021-05-05T02:44:09.395Z] Executed 'Functions.iot-hub-trigger' (Succeeded, Id=802803a5-eae9-4401-a1f4-176631456ce4, Duration=245ms)

    每次調用函數時,輸出中都會有一個 Executing 'Functions.iot-hub-trigger'/Executed 'Functions.iot-hub-trigger' 塊,因此您可以看到每次函數調用處理了多少消息。

  3. 確保您的 IoT 設備正在運行。您將看到新的土壤濕度消息出現在函數應用程式中。

  4. 停止並重新啟動函數應用程式。您將看到它不會再次處理以前的消息,只會處理新消息。

💁 VS Code 還支持調試您的函數。您可以通過點擊每行代碼開始處的邊框設置斷點,或將光標放在代碼行上並選擇運行 -> 切換斷點,或按 F9。您可以通過選擇運行 -> 開始調試、按 F5 或選擇運行和調試窗格並選擇開始調試按鈕來啟動調試器。通過這樣做,您可以查看正在處理的事件的詳細信息。

故障排除

  • 如果您收到以下錯誤:

    The listener for function 'Functions.iot-hub-trigger' was unable to start. Microsoft.WindowsAzure.Storage: Connection refused. System.Net.Http: Connection refused. System.Private.CoreLib: Connection refused.

    檢查 Azurite 是否正在運行,並且您已將 local.settings.json 文件中的 AzureWebJobsStorage 設置為 UseDevelopmentStorage=true

  • 如果您收到以下錯誤:

    System.Private.CoreLib: Exception while executing function: Functions.iot-hub-trigger. System.Private.CoreLib: Result: Failure Exception: AttributeError: 'list' object has no attribute 'get_body'

    檢查您是否已將 function.json 文件中的 cardinality 設置為 one

  • 如果您收到以下錯誤:

    Azure.Messaging.EventHubs: The path to an Event Hub may be specified as part of the connection string or as a separate value, but not both.  Please verify that your connection string does not have the `EntityPath` token if you are passing an explicit Event Hub name. (Parameter 'connectionString').

    檢查您是否已將 function.json 文件中的 eventHubName 設置為空字符串。

從無伺服器代碼發送直接方法請求

到目前為止,您的函數應用程式正在使用事件中樞兼容端點監聽來自 IoT 中樞的消息。您現在需要向 IoT 設備發送命令。這是通過使用註冊管理器通過 IoT 中樞的不同連接來完成的。註冊管理器是一個工具,允許您查看註冊到 IoT 中樞的設備,並通過發送雲到設備消息、直接方法請求或更新設備雙向來與這些設備通信。您還可以使用它來註冊、更新或刪除 IoT 中樞中的 IoT 設備。

要連接到註冊管理器,您需要一個連接字符串。

任務 - 獲取註冊管理器連接字符串

  1. 要獲取連接字符串,請運行以下命令:

    az iot hub connection-string show --policy-name service \
    --output table \
    --hub-name <hub_name>

    <hub_name> 替換為您用於 IoT 中樞的名稱。

    連接字符串是為 ServiceConnect 策略請求的,使用 --policy-name service 參數。當您請求連接字符串時,您可以指定該連接字符串允許的權限。ServiceConnect 策略允許您的代碼連接並向 IoT 設備發送消息。

    ✅ 進行一些研究:閱讀 IoT 中樞權限文檔 中的不同策略。

  2. 在 VS Code 中打開 local.settings.json 文件。在 Values 部分內添加以下附加值:

    "REGISTRY_MANAGER_CONNECTION_STRING": "<connection string>"

    <connection string> 替換為上一步中的值。您需要在上面的行後添加逗號以使其成為有效的 JSON。

任務 - 向設備發送直接方法請求

  1. 註冊管理器的 SDK 可通過 Pip 包獲得。將以下行添加到 requirements.txt 文件中以添加對此包的依賴:

    azure-iot-hub
  2. 確保 VS Code 終端已激活虛擬環境,並運行以下命令以安裝 Pip 包:

    pip install -r requirements.txt
  3. 將以下導入添加到 __init__.py 文件中:

    import json
    import os
    from azure.iot.hub import IoTHubRegistryManager
    from azure.iot.hub.models import CloudToDeviceMethod

    這將導入一些系統庫,以及與註冊管理器交互並發送直接方法請求的庫。

  4. main 方法中刪除代碼,但保留方法本身。

  5. main 方法中,添加以下代碼:

    body = json.loads(event.get_body().decode('utf-8'))
    device_id = event.iothub_metadata['connection-device-id']

    logging.info(f'Received message: {body} from {device_id}')

    此代碼提取包含 IoT 設備發送的 JSON 消息的事件正文。

    然後從消息中提取設備 ID。事件的正文包含作為遙測發送的消息,iothub_metadata 字典包含 IoT 中樞設置的屬性,例如發送者的設備 ID 和消息發送的時間。

    然後記錄此信息。當您在本地運行函數應用程式時,您將在終端中看到此日誌。

  6. 在此下面,添加以下代碼:

    soil_moisture = body['soil_moisture']

    if soil_moisture > 450:
    direct_method = CloudToDeviceMethod(method_name='relay_on', payload='{}')
    else:
    direct_method = CloudToDeviceMethod(method_name='relay_off', payload='{}')

    此代碼從消息中獲取土壤濕度。然後檢查土壤濕度,並根據值創建一個直接方法請求的輔助類,用於 relay_onrelay_off 直接方法。方法請求不需要有效負載,因此發送一個空的 JSON 文檔。

  7. 在此下面添加以下代碼:

    logging.info(f'Sending direct method request for {direct_method.method_name} for device {device_id}')

    registry_manager_connection_string = os.environ['REGISTRY_MANAGER_CONNECTION_STRING']
    registry_manager = IoTHubRegistryManager(registry_manager_connection_string)

    此代碼從 local.settings.json 文件中加載 REGISTRY_MANAGER_CONNECTION_STRING。此文件中的值作為環境變量提供,這些可以使用 os.environ 函數讀取,該函數返回所有環境變量的字典。

    💁 當此代碼部署到雲端時,local.settings.json 文件中的值將設置為應用程式設置,這些設置可以從環境變量中讀取。

    然後代碼使用連接字符串創建註冊管理器輔助類的實例。

  8. 在此下面添加以下代碼:

    registry_manager.invoke_device_method(device_id, direct_method)

    logging.info('Direct method request sent!')

    此代碼告訴註冊管理器向發送遙測的設備發送直接方法請求。

    💁 在您使用 MQTT 的早期課程中創建的應用程式版本中,繼電器控制命令發送到所有設備。代碼假設您只有一個設備。此版本的代碼將方法請求發送到單個設備,因此如果您有多個土壤濕度傳感器和繼電器的設置,它將發送正確的直接方法請求到正確的設備。

  9. 運行函數應用程式,並確保您的 IoT 設備正在發送數據。您將看到消息被處理並發送直接方法請求。通過將土壤濕度傳感器移入和移出土壤來查看值的變化以及繼電器的開啟和關閉

💁 您可以在 code/functions 文件夾中找到此代碼。

將您的無伺服器代碼部署到雲端

您的代碼現在在本地運行,因此下一步是將函數應用程式部署到雲端。

任務 - 創建雲資源

您的函數應用程式需要部署到 Azure 中的函數應用程式資源,位於您為 IoT 中樞創建的資源組內。您還需要在 Azure 中創建一個存儲帳戶,以替換您在本地運行的模擬存儲。

  1. 運行以下命令創建存儲帳戶:

    az storage account create --resource-group soil-moisture-sensor \
    --sku Standard_LRS \
    --name <storage_name>

    <storage_name> 替換為您的存儲帳戶名稱。這需要是全局唯一的,因為它構成了用於訪問存儲帳戶的 URL 的一部分。您只能使用小寫字母和數字,不能使用其他字符,並且限制為 24 個字符。使用類似 sms 的名稱,並在末尾添加唯一標識符,例如一些隨機單詞或您的名字。

    --sku Standard_LRS 選擇定價層,選擇最低成本的通用帳戶。沒有免費層存儲,您按使用量付費。成本相對較低,最昂貴的存儲每月每 GB 存儲不到 0.05 美元。

    ✅ 在 Azure 存儲帳戶定價頁面 上閱讀定價。

  2. 運行以下命令創建函數應用程式:

    az functionapp create --resource-group soil-moisture-sensor \
    --runtime python \
    --functions-version 3 \
    --os-type Linux \
    --consumption-plan-location <location> \
    --storage-account <storage_name> \
    --name <functions_app_name>

    <location> 替換為您在上一課中創建資源組時使用的位置。

    <storage_name> 替換為您在上一步中創建的存儲帳戶名稱。

    <functions_app_name> 替換為您的函數應用程式的唯一名稱。這需要是全局唯一的,因為它構成了用於訪問函數應用程式的 URL 的一部分。使用類似 soil-moisture-sensor- 的名稱,並在末尾添加唯一標識符,例如一些隨機單詞或您的名字。

    --functions-version 3 選項設置要使用的 Azure Functions 版本。版本 3 是最新版本。

    --os-type Linux 告訴函數運行時使用 Linux 作為託管這些函數的操作系統。函數可以在 Linux 或 Windows 上託管,具體取決於使用的編程語言。Python 應用程式僅支持在 Linux 上運行。

任務 - 上傳您的應用程式設置

當您開發函數應用程式時,您將一些設置存儲在 local.settings.json 文件中,用於 IoT 中樞的連接字符串。這些需要寫入 Azure 中的函數應用程式應用程式設置,以便您的代碼可以使用它們。

🎓 local.settings.json 文件僅用於本地開發設置,不應檢入源代碼控制,例如 GitHub。當部署到雲端時,使用應用程式設置。應用程式設置是託管在雲端的鍵/值對,可以從環境變量中讀取,無論是在代碼中還是運行時在連接您的代碼到 IoT 中樞時。

  1. 運行以下命令將 IOT_HUB_CONNECTION_STRING 設置設置在函數應用程式應用程式設置中:

    az functionapp config appsettings set --resource-group soil-moisture-sensor \
    --name <functions_app_name> \
    --settings "IOT_HUB_CONNECTION_STRING=<connection string>"

    <functions_app_name> 替換為您用於函數應用程式的名稱。

    <connection string> 替換為 local.settings.json 文件中的 IOT_HUB_CONNECTION_STRING 值。

  2. 重複上述步驟,但將 REGISTRY_MANAGER_CONNECTION_STRING 的值設置為 local.settings.json 文件中的相應值。

當您運行這些命令時,它們還會輸出函數應用程式的所有應用程式設置的列表。您可以使用此列表檢查您的值是否設置正確。

💁 您將看到一個已設置的 AzureWebJobsStorage 值。在您的 local.settings.json 文件中,這設置為使用本地存儲模擬器的值。當您創建函數應用程式時,您將存儲帳戶作為參數傳遞,並且此設置會自動設置。

任務 - 將您的函數應用程式部署到雲端

現在函數應用程式已準備好,您的代碼可以部署。

  1. 從 VS Code 終端運行以下命令以發布您的函數應用程式:

    func azure functionapp publish <functions_app_name>

    <functions_app_name> 替換為您用於函數應用程式的名稱。

代碼將被打包並發送到函數應用程式,然後進行部署和啟動。會有大量的控制台輸出,最後會確認部署並列出已部署的函數。在這種情況下,列表中只會包含觸發器。

Deployment successful.
Remote build succeeded!
Syncing triggers...
Functions in soil-moisture-sensor:
iot-hub-trigger - [eventHubTrigger]

確保您的 IoT 設備正在運行。通過調整土壤濕度或將傳感器移入和移出土壤來改變濕度水平。您將看到繼電器隨著土壤濕度的變化而開啟和關閉。


🚀 挑戰

在上一課中,您通過在繼電器開啟時取消訂閱 MQTT 訊息以及在其關閉後短時間內取消訂閱來管理繼電器的計時。在這裡您不能使用這種方法 - 您無法取消訂閱您的 IoT 中樞觸發器。

考慮在您的函數應用程式中處理此問題的不同方法。

課後測驗

課後測驗

回顧與自學

作業

添加手動繼電器控制