共用方式為


HoloLens (第 1 代) 和 Azure 313:IoT 中樞 服務

注意

混合實境學院教學課程的設計是以 HoloLens (第 1 代) 和混合實境沉浸式頭戴裝置為準。 因此,對於仍在尋找這些裝置開發指引的開發人員而言,我們覺得這些教學課程很重要。 這些教學課程不會使用用於 HoloLens 2 的最新工具組或互動進行更新。 系統會保留這些資訊,以繼續在支援的裝置上運作。 未來將會張貼一系列新的教學課程,以示範如何為 HoloLens 2 進行開發。 張貼這些教學課程的連結將會更新此通知。

課程結果

在此課程中,您將瞭解如何在執行Ubuntu16.4作業系統的虛擬機上實作 Azure IoT 中樞服務然後,Azure 函式應用程式將用來接收來自 Ubuntu VM 的訊息,並將結果儲存在 Azure 資料表服務中。 然後,您將能夠在 Microsoft HoloLens 或沉浸式 (VR) 頭戴式裝置上使用 Power BI 來檢視此數據

本課程 的內容適用於 IoT Edge裝置,不過基於本課程的目的,焦點會放在虛擬機環境上,因此不需要存取實體Edge裝置。

完成本課程后,您將瞭解如何:

  • IoT Edge 模組 部署至代表 IoT 裝置的虛擬機 (Ubuntu 16 OS)。
  • 將 Azure 自訂視覺 Tensorflow 模型新增至 Edge 模組,並使用程式代碼來分析儲存在容器中的影像。
  • 設定模組以將分析結果訊息傳回至您的 IoT 中樞 服務
  • 使用 Azure 函式應用程式將訊息儲存在 Azure 資料表
  • 設定 Power BI 以收集儲存的訊息並建立報表。
  • 在 Power BI將 IoT 訊息資料可視化。

您將使用的服務包括:

  • Azure IoT 中樞 是一種Microsoft Azure 服務,可讓開發人員連線、監視和管理IoT資產。 如需詳細資訊,請流覽 Azure IoT 中樞 服務頁面

  • Azure Container Registry 是一種Microsoft Azure 服務,可讓開發人員儲存各種容器類型的容器映射。 如需詳細資訊,請流覽 Azure Container Registry Service 頁面

  • Azure 函式應用程式 是一種Microsoft Azure 服務,可讓開發人員在 Azure 中執行小型程式碼「函式」。 這提供將工作委派給雲端的方式,而不是您的本機應用程式,這有許多優點。 Azure Functions 支援數種開發語言,包括 C#、F#、Node.js、Java 和 PHP。 如需詳細資訊,請流覽 Azure Functions 頁面

  • Azure 儲存體:數據表是一種Microsoft Azure 服務,可讓開發人員將結構化、非 SQL、數據儲存在雲端中,使其可在任何地方輕鬆存取。 服務擁有無架構的設計,可視需要演進數據表,因此非常有彈性。 如需詳細資訊,請流覽 Azure 數據表 頁面

本課程將教導您如何設定及使用 IoT 中樞 服務,然後將裝置提供的響應可視化。 您必須將這些概念套用至您可能要建置的自訂 IoT 中樞 服務設定。

裝置支援

課程 HoloLens 沉浸式頭戴裝置
MR 和 Azure 313:IoT 中樞 服務 ✔️ ✔️

必要條件

如需使用混合實境進行開發的最新必要條件,包括搭配 Microsoft HoloLens,請瀏覽 安裝工具 一文。

注意

本教學課程專為具備 Python 基本經驗的開發人員所設計。 另請注意,本檔內的必要條件和書面指示代表在撰寫期間經過測試和驗證的內容(2018 年 7 月)。 您可以自由使用最新的軟體,如安裝工具文章中所列,不過不應該假設本課程中的資訊會完全符合您在較新的軟體中找到的內容,而不是下面所列。

需要下列硬體和軟體:

  • Windows 10 Fall Creators Update (或更新版本), 已啟用開發人員模式

    警告

    您無法在 Windows 10 家用版 Edition 上使用 Hyper-V 執行虛擬機。

  • Windows 10 SDK (最新版本)

  • 已啟用 HoloLens、 開發人員模式

  • Visual Studio 2017.15.4 (僅用來存取 Azure Cloud Explorer)

  • 適用於 Azure 和 IoT 中樞 服務的因特網存取。 如需詳細資訊,請遵循此連結以 IoT 中樞 服務頁面

  • Machine Learning 模型。 如果您還沒有準備好使用模型, 您可以使用本課程所提供的模型。

  • 在您的 Windows 10 開發電腦上啟用 Hyper-V 軟體。

  • 執行Ubuntu的虛擬機(16.4或18.4),在開發電腦上執行,或者您也可以使用執行Linux的個別電腦(Ubuntu 16.4或18.4)。 如需如何使用 Hyper-V 在 Windows 上使用 Hyper-V 建立 VM 的詳細資訊,請參閱一章

在您開始使用 Intune 之前

  1. 設定及測試 HoloLens。 如果您需要設定 HoloLens 的支援, 請務必流覽 HoloLens 設定文章
  2. 開始開發新的 HoloLens 應用程式時,最好執行 校正感測器微調 (有時有助於為每個使用者執行這些工作)。

如需校正的說明,請遵循此 連結至 HoloLens 校正文章

如需感測器微調的說明,請遵循此 連結至 HoloLens 感測器微調文章

  1. 使用 Hyper-V 設定您的 Ubuntu 虛擬機。 下列資源可協助您完成此程式。

    1. 首先,請遵循此鏈接來 下載Ubuntu16.04.4 LTS(Xenial Xerus) ISO選取 64 位電腦 (AMD64) 桌面映像
    2. 請確定 Windows 10 計算機上已啟用 Hyper-V 。 您可以遵循此連結,以取得在 Windows 10 上安裝和啟用 Hyper-V 的指引
    3. 啟動 Hyper-V 並建立新的 Ubuntu VM。 您可以遵循此連結 ,以取得如何使用 Hyper-V 建立 VM 的逐步指南。 當要求 「從可開機映射檔安裝操作系統」時,請選取您稍早下載的 Ubuntu ISO

    注意

    不建議使用 Hyper-V 快速建立

第 1 章 - 擷取 自訂視覺 模型

透過本課程,您將能夠存取預先建置的 自訂視覺 模型,以偵測影像中的鍵盤和滑鼠。 如果您使用此選項,請繼續進行 第 2 章。

不過,如果您想要使用自己的 自訂視覺 模型,可以遵循下列步驟:

  1. 在您的 自訂視覺 專案中,移至 [效能] 索引標籤。

    警告

    您的模型必須使用 精簡 定義域來導出模型。 您可以在項目的設定中變更模型定義域。

    效能索引標籤

  2. 選取您要導出的反覆專案,然後按兩下 [匯出]。 刀鋒視窗隨即出現。

    匯出刀鋒視窗

  3. 在刀鋒視窗中,按兩下 [Docker 檔案]。

    選取 docker

  4. 單擊 下拉功能表中的 [Linux ],然後按兩下 [ 下載]。

    按兩下 [下載]

  5. 將內容解壓縮。 您稍後將在本課程中使用。

第 2 章 - Container Registry Service

Container Registry Service 是用來裝載容器的存放庫。

您將在此課程中建置及使用的 IoT 中樞 服務,指的是 Container Registry Service,以取得要部署在 Edge 裝置中的容器。

  1. 首先,請遵循此 連結至 Azure 入口網站,並使用您的認證登入。

  2. 移至 [建立資源 ] 並尋找 Container Registry

    容器登錄

  3. 按一下 [建立]

    顯示選取 [建立] 位置的螢幕快照。

  4. 設定服務設定參數:

    1. 插入項目的名稱,在此範例中,其稱為 IoTCRegistry

    2. 選擇資源群組或建立新的群組。 資源群組提供一種方式來監視、控制存取、布建和管理 Azure 資產集合的計費。 建議將所有與單一專案相關聯的 Azure 服務(例如,例如這些課程)保留在通用資源群組下)。

    3. 設定服務的位置。

    4. 將 [系統管理員使用者] 設定為 [啟用]。

    5. 將 SKU 設定[基本]。

    顯示將 SKU 設定為 [基本] 位置的螢幕快照。

  5. 按兩下 [ 建立 ],並等候服務建立。

  6. 一旦通知快顯通知您成功建立 Container Registry,請按兩下 [移至 資源] 以重新導向至您的服務頁面。

    顯示選取 [移至資源位置] 的螢幕快照。

  7. 在 [ Container Registry Service] 頁面中,按兩下 [ 存取密鑰]。

  8. 記下下列參數的記事本(您可以使用記事本):

    1. 登入伺服器
    2. 使用者名稱
    3. 密碼

    顯示檢視 [登入伺服器]、[使用者名稱] 和 [密碼] 參數位置的螢幕快照。

第 3 章 - IoT 中樞 服務

現在,您將開始建立和設定 IoT 中樞 服務

  1. 如果尚未登入,請登入 Azure 入口網站

  2. 登入之後,按兩下左上角的 [建立資源],然後搜尋 IoT 中樞,然後按兩下 Enter

顯示 [所有專案] 視窗開啟的螢幕快照。搜尋結果中的 I O T 中樞和左上角的 [建立資源] 會以紅色圓形。

  1. 新頁面將提供記憶體帳戶服務的描述。 在此提示的左下角,按兩下 [ 建立] 按鈕,以建立此服務的實例。

    顯示 [I O T 中樞概觀] 頁面的螢幕快照。

  2. 按兩下 [ 建立] 之後,會出現面板:

    1. 選擇資源群組或建立新的群組。 資源群組提供一種方式來監視、控制存取、布建和管理 Azure 資產集合的計費。 建議將所有與單一專案相關聯的 Azure 服務(例如,例如這些課程)保留在通用資源群組下)。

      如果您想要深入瞭解 Azure 資源群組,請遵循此 連結以瞭解如何管理資源群組

    2. 選取適當的 位置 (在此課程中建立的所有服務使用相同的位置)。

    3. 插入此服務實例所需的 名稱

  3. 在頁面底部,按兩下一步:大小和縮放。

    顯示 [I O T 中樞基本概念] 頁面的螢幕快照。下一個大小和小數字數會在頁面底部以紅色圓形。

  4. 在此頁面中,選取您的定價和調整層(如果這是您第一個 IoT 中樞 服務實例,您應該可以使用免費層。

  5. 按兩下 [ 檢閱 + 建立]。

    顯示 I O T 中樞大小和縮放頁面的螢幕快照。F 1 免費層會在 [定價和調整層] 欄位中選取。檢閱和建立會在頁面底部以紅色圓形。

  6. 檢閱您的設定,然後按兩下 [ 建立]。

    顯示 [I O T 中樞檢閱和建立] 頁面的螢幕快照。Create 會在頁面底部以紅色圓圈。

  7. 當通知快顯通知您成功建立 IoT 中樞 服務之後,請按兩下 [移至資源] 以重新導向至您的 [服務] 頁面。

    顯示部署成功通知的螢幕快照。[移至資源] 按鈕會以紅色圓圈。

  8. 在左側捲動側邊面板,直到您看到 [自動 裝置管理],按兩下 [IoT Edge]。

    此螢幕快照顯示 [自動 裝置管理] 下功能表中已選取的 [I O T Edge]。

  9. 在右側顯示的視窗中,按兩下 [ 新增IoT Edge裝置]。 刀鋒視窗會出現在右側。

  10. 在刀鋒視窗中,為您的新裝置提供裝置 識別碼 (您選擇的名稱)。 然後,按一下 [儲存]如果您有自動產生刻度,主要次要密鑰將會自動產生。

    顯示 [新增裝置] 頁面的螢幕快照。Edge Device 0 1 會在 [裝置標識符] 字段中輸入。核取 [自動產生金鑰] 方塊。

  11. 您將流覽回 [IoT Edge 裝置 ] 區段,其中會列出您的新裝置。 按兩下您的新裝置(下圖中以紅色框線)。

    顯示 [I O T Edge 裝置] 頁面的螢幕快照。頁面底部的Edge裝置旁邊會核取此方塊。

  12. 在出現的 [裝置詳細數據] 頁面上,取得連接字串 (主鍵) 的複本。

    顯示 [裝置詳細數據] 頁面的螢幕快照。連接字串主鍵會以紅色圓形。

  13. 返回左側的面板,然後按兩下 [ 共用存取原則],以開啟它。

  14. 在出現的頁面上,按兩下 [iothubowner],畫面右側會出現刀鋒視窗。

  15. 記下 [連接字串] 的 [記事本] (主鍵),以供稍後在將連接字串設定為裝置時使用。

    顯示 [共用存取原則] 頁面的螢幕快照,其位於 [設定] 底下。[原則] 底下已選取 [I O T 中樞擁有者]。在彈出視窗中,連接字串 主鍵欄位會以紅色圓圈。

第 4 章 - 設定開發環境

若要建立和部署 IoT 中樞 Edge 的模組,您必須在執行 Windows 10 的開發電腦上安裝下列元件:

  1. Docker for Windows 會要求您建立帳戶才能下載。

    下載適用於 Windows 的 Docker

    重要

    Docker 需要 Windows 10 專業版企業版 14393Windows Server 2016 RTM 才能執行。 如果您正在執行其他版本的 Windows 10,您可以嘗試使用 Docker 工具箱安裝 Docker。

  2. Python 3.6

    下載 python 3.6

  3. Visual Studio Code (也稱為 VS Code)

    下載 VS Code

安裝上述軟體之後,您必須重新啟動電腦。

第 5 章 - 設定 Ubuntu 環境

現在您可以繼續設定執行UbuntuOS的裝置。 請遵循下列步驟,安裝必要的軟體,在面板上部署容器:

重要

您應該一律在終端機命令前面加上 sudo ,以系統管理員使用者身分執行。 亦即:

sudo docker \<option> \<command> \<argument>
  1. 開啟 Ubuntu 終端機,並使用下列命令來安裝 pip

    [!HINT] 您可以使用鍵盤快捷方式輕鬆地開啟 終端機Ctrl + Alt + T

        sudo apt-get install python-pip
    
  2. 在此章節中,您可能會收到 [終端機] 的提示,以取得使用裝置記憶體的許可權,以及輸入 y/n (是或否),輸入 'y',然後按 Enter 鍵接受。

  3. 完成該命令之後,請使用下列命令來安裝 curl

        sudo apt install curl
    
  4. 安裝 pipcurl 之後,請使用下列命令來安裝 IoT Edge 運行時間,這是部署及控制面板上的模組的必要條件:

        curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > ./microsoft-prod.list
    
        sudo cp ./microsoft-prod.list /etc/apt/sources.list.d/
    
        curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
    
        sudo cp ./microsoft.gpg /etc/apt/trusted.gpg.d/
    
        sudo apt-get update
    
        sudo apt-get install moby-engine
    
        sudo apt-get install moby-cli
    
        sudo apt-get update
    
        sudo apt-get install iotedge
    
  5. 此時,系統會提示您開啟運行時間組態檔,以在建立 IoT 中樞 服務時,插入您記下 [記事本] 的裝置連接字串第 3 章的步驟 14)。 在終端機上執行下列程式代碼行,以開啟該檔案:

        sudo nano /etc/iotedge/config.yaml
    
  6. config.yaml 檔案隨即顯示,可供您編輯:

    警告

    當這個檔案開啟時,它可能會有點令人困惑。 您將會在終端機本身內編輯此檔案的文字。

    1. 使用鍵盤上的箭頭鍵向下捲動(您將需要向下捲動一點),才能到達包含的行:”

      <在這裡>新增裝置連接字串」。

    2. 以您稍早注意到的裝置連接字串取代行,包括括號

  7. 將連接字串就地放在鍵盤上,按 Ctrl-X 鍵以儲存盤案。 它會要求您輸入 Y 以確認。然後,按 Enter 鍵以確認。 您將返回一般 終端機

  8. 一旦這些命令都順利執行,您就會安裝 IoT Edge運行時間。 初始化之後,運行時間會在每次啟動裝置電源時自行啟動,且會位於背景中,等待從 IoT 中樞 服務部署模組。

  9. 執行下列命令列來初始化 IoT Edge 執行時間

        sudo systemctl restart iotedge
    

    重要

    如果您對 .yaml 檔案或上述設定進行變更,則必須在終端機內再次執行上述重新啟動行。

  10. 執行下列命令行來 檢查 IoT Edge 執行時間 狀態。 運行時間應該會以綠色文字顯示狀態為作用中(執行中)。

        sudo systemctl status iotedge
    
  11. 按 Ctrl-C 鍵以結束狀態頁面。 您可以輸入下列命令,確認 IoT Edge 執行時間 正在正確提取容器:

        sudo docker ps
    
  12. 應該會出現兩個 (2) 個容器的清單。 這些是 IoT 中樞 服務自動建立的預設模組(edgeAgent 和edgeHub)。 建立和部署自己的模組之後,這些模組就會出現在預設模組下方的清單中。

第 6 章 - 安裝擴充功能

重要

接下來的幾章 (6-9) 將在您的 Windows 10 計算機上執行。

  1. 開啟 VS Code

  2. 按兩下 VS Code 左側列的 [ 延伸模組 ] 按鈕,以開啟 [ 延伸模組] 面板

  3. 搜尋並安裝下列延伸模組(如下圖所示):

    1. Azure IoT Edge
    2. Azure IoT 工具組
    3. Docker

    顯示延伸模組視窗的螢幕快照。Azure I O T Edge、Azure I O T Toolkit 和 Docker 會以紅色圓形。

  4. 安裝擴充功能之後,請關閉並重新開啟 VS Code。

  5. 再次開啟 VS Code 後,流覽至 [檢視>整合式終端機]。

  6. 您現在將會安裝 Cookiecutter。 在終端機中,執行下列bash命令:

        pip install --upgrade --user cookiecutter
    

    [!HINT] 如果您在此命令時遇到問題:

    1. 重新啟動 VS Code,以及/或您的電腦。
    2. 您可能需要將 VS Code 終端機切換 至您用來安裝 Python 的終端機 ,也就是 Powershell (特別是在您的電腦上已安裝 Python 環境的情況下)。 開啟終端機后,您會在終端機右側找到下拉功能表。 顯示下拉功能表上已選取 1 個 powershell 的螢幕快照。
    3. 請確定 已將 Python 安裝路徑新增為 電腦上的環境變數 。 Cookiecutter 應該是相同位置路徑的一部分。 如需環境變數的詳細資訊,請遵循此連結。
  7. 一旦 Cookiecutter 完成安裝,您應該重新啟動電腦,讓 Cookiecutter 在您的系統環境中辨識為命令。

第 7 章 - 建立容器解決方案

此時,您必須使用 模組建立容器,才能推送至 Container Registry。 一旦您推送容器,您將使用 IoT 中樞 Edge 服務將它部署至執行 IoT Edge 運行時間裝置。

  1. 從 VS Code,按兩下 [檢視>命令選擇區]。

  2. 在調色盤中,搜尋並執行 Azure IoT Edge:新的 IoT Edge 解決方案

  3. 流覽至您想要建立解決方案的位置。 按 Enter 鍵,以接受位置。

  4. 為您的解決方案命名。 按 Enter 鍵,以確認您提供的名稱。

  5. 現在系統會提示您選擇解決方案的範本架構。 按兩下 [Python 模組]。 按 Enter 鍵,以確認這個選擇。

  6. 為模組命名。 按 Enter 鍵,確認模組的名稱。 請務必記下模組名稱的記事(記事本),因為稍後會用到。

  7. 您會發現預先建置 的 Docker 映像存放庫 地址會出現在調色盤上。 看起來會像這樣:

    localhost:5000/-您的模組名稱。

  8. 刪除 localhost:5000,並在其位置插入 Container Registry 登入伺服器位址,您在建立 Container Registry Service 時記下此位址(在第 2 章的步驟 8 中)。 按 Enter 鍵,確認位址。

  9. 此時,將會建立包含 Python 模組範本的解決方案,而且其結構會顯示在 畫面左側的 [探索] 索引標籤中的 VS Code 中。 如果 [探索] 索引標籤未開啟,您可以按下左側列的最上層按鈕加以開啟。

    顯示 [探索] 索引標籤按鈕的螢幕快照,其類似於 2 個堆疊的紙張。

  10. 本章的最後一個步驟是從 [探索] 索引標籤內按兩下並開啟 .env 檔案,然後新增您的 Container Registry 使用者名稱和密碼。 Git 會忽略此檔案,但在建置容器時,將會設定認證來存取 Container Registry Service

    顯示命令視窗的螢幕快照,其中包含第 1 行輸入的 Container Registry 使用者名稱文字,以及第 2 行輸入的 Container Registry Password。

第 8 章 - 編輯您的容器解決方案

您現在會藉由更新下列檔案來完成容器解決方案:

  • main.py python 腳本。
  • requirements.txt
  • deployment.template.json
  • Dockerfile.amd64

接著,您將建立 images 資料夾,由 python 腳本用來檢查影像是否與 自訂視覺 模型相符。 最後,您將新增 labels.txt 檔案,以協助讀取您的模型,以及 model.pb 檔案,也就是您的模型。

  1. 開啟 VS Code 後,流覽至模組資料夾,並尋找名為 main的腳本.py。 按兩下將它開啟。

  2. 刪除檔案的內容,並插入下列程式代碼:

    # Copyright (c) Microsoft. All rights reserved.
    # Licensed under the MIT license. See LICENSE file in the project root for
    # full license information.
    
    import random
    import sched, time
    import sys
    import iothub_client
    from iothub_client import IoTHubModuleClient, IoTHubClientError, IoTHubTransportProvider
    from iothub_client import IoTHubMessage, IoTHubMessageDispositionResult, IoTHubError
    import json
    import os
    import tensorflow as tf
    import os
    from PIL import Image
    import numpy as np
    import cv2
    
    # messageTimeout - the maximum time in milliseconds until a message times out.
    # The timeout period starts at IoTHubModuleClient.send_event_async.
    # By default, messages do not expire.
    MESSAGE_TIMEOUT = 10000
    
    # global counters
    RECEIVE_CALLBACKS = 0
    SEND_CALLBACKS = 0
    
    TEMPERATURE_THRESHOLD = 25
    TWIN_CALLBACKS = 0
    
    # Choose HTTP, AMQP or MQTT as transport protocol.  Currently only MQTT is supported.
    PROTOCOL = IoTHubTransportProvider.MQTT
    
    
    # Callback received when the message that we're forwarding is processed.
    def send_confirmation_callback(message, result, user_context):
        global SEND_CALLBACKS
        print ( "Confirmation[%d] received for message with result = %s" % (user_context, result) )
        map_properties = message.properties()
        key_value_pair = map_properties.get_internals()
        print ( "    Properties: %s" % key_value_pair )
        SEND_CALLBACKS += 1
        print ( "    Total calls confirmed: %d" % SEND_CALLBACKS )
    
    
    def convert_to_opencv(image):
        # RGB -> BGR conversion is performed as well.
        r,g,b = np.array(image).T
        opencv_image = np.array([b,g,r]).transpose()
        return opencv_image
    
    def crop_center(img,cropx,cropy):
        h, w = img.shape[:2]
        startx = w//2-(cropx//2)
        starty = h//2-(cropy//2)
        return img[starty:starty+cropy, startx:startx+cropx]
    
    def resize_down_to_1600_max_dim(image):
        h, w = image.shape[:2]
        if (h < 1600 and w < 1600):
            return image
    
        new_size = (1600 * w // h, 1600) if (h > w) else (1600, 1600 * h // w)
        return cv2.resize(image, new_size, interpolation = cv2.INTER_LINEAR)
    
    def resize_to_256_square(image):
        h, w = image.shape[:2]
        return cv2.resize(image, (256, 256), interpolation = cv2.INTER_LINEAR)
    
    def update_orientation(image):
        exif_orientation_tag = 0x0112
        if hasattr(image, '_getexif'):
            exif = image._getexif()
            if (exif != None and exif_orientation_tag in exif):
                orientation = exif.get(exif_orientation_tag, 1)
                # orientation is 1 based, shift to zero based and flip/transpose based on 0-based values
                orientation -= 1
                if orientation >= 4:
                    image = image.transpose(Image.TRANSPOSE)
                if orientation == 2 or orientation == 3 or orientation == 6 or orientation == 7:
                    image = image.transpose(Image.FLIP_TOP_BOTTOM)
                if orientation == 1 or orientation == 2 or orientation == 5 or orientation == 6:
                    image = image.transpose(Image.FLIP_LEFT_RIGHT)
        return image
    
    
    def analyse(hubManager):
    
        messages_sent = 0;
    
        while True:
            #def send_message():
            print ("Load the model into the project")
            # These names are part of the model and cannot be changed.
            output_layer = 'loss:0'
            input_node = 'Placeholder:0'
    
            graph_def = tf.GraphDef()
            labels = []
    
            labels_filename = "labels.txt"
            filename = "model.pb"
    
            # Import the TF graph
            with tf.gfile.FastGFile(filename, 'rb') as f:
                graph_def.ParseFromString(f.read())
                tf.import_graph_def(graph_def, name='')
    
            # Create a list of labels
            with open(labels_filename, 'rt') as lf:
                for l in lf:
                    labels.append(l.strip())
            print ("Model loaded into the project")
    
            results_dic = dict()
    
            # create the JSON to be sent as a message
            json_message = ''
    
            # Iterate through images 
            print ("List of images to analyse:")
            for file in os.listdir('images'):
                print(file)
    
                image = Image.open("images/" + file)
    
                # Update orientation based on EXIF tags, if the file has orientation info.
                image = update_orientation(image)
    
                # Convert to OpenCV format
                image = convert_to_opencv(image)
    
                # If the image has either w or h greater than 1600 we resize it down respecting
                # aspect ratio such that the largest dimension is 1600
                image = resize_down_to_1600_max_dim(image)
    
                # We next get the largest center square
                h, w = image.shape[:2]
                min_dim = min(w,h)
                max_square_image = crop_center(image, min_dim, min_dim)
    
                # Resize that square down to 256x256
                augmented_image = resize_to_256_square(max_square_image)
    
                # The compact models have a network size of 227x227, the model requires this size.
                network_input_size = 227
    
                # Crop the center for the specified network_input_Size
                augmented_image = crop_center(augmented_image, network_input_size, network_input_size)
    
                try:
                    with tf.Session() as sess:     
                        prob_tensor = sess.graph.get_tensor_by_name(output_layer)
                        predictions, = sess.run(prob_tensor, {input_node: [augmented_image] })
                except Exception as identifier:
                    print ("Identifier error: ", identifier)
    
                print ("Print the highest probability label")
                highest_probability_index = np.argmax(predictions)
                print('FINAL RESULT! Classified as: ' + labels[highest_probability_index])
    
                l = labels[highest_probability_index]
    
                results_dic[file] = l
    
                # Or you can print out all of the results mapping labels to probabilities.
                label_index = 0
                for p in predictions:
                    truncated_probablity = np.float64(round(p,8))
                    print (labels[label_index], truncated_probablity)
                    label_index += 1
    
            print("Results dictionary")
            print(results_dic)
    
            json_message = json.dumps(results_dic)
            print("Json result")
            print(json_message)
    
            # Initialize a new message
            message = IoTHubMessage(bytearray(json_message, 'utf8'))
    
            hubManager.send_event_to_output("output1", message, 0)
    
            messages_sent += 1
            print("Message sent! - Total: " + str(messages_sent))      
            print('----------------------------')
    
            # This is the wait time before repeating the analysis
            # Currently set to 10 seconds
            time.sleep(10)
    
    
    class HubManager(object):
    
        def __init__(
                self,
                protocol=IoTHubTransportProvider.MQTT):
            self.client_protocol = protocol
            self.client = IoTHubModuleClient()
            self.client.create_from_environment(protocol)
    
            # set the time until a message times out
            self.client.set_option("messageTimeout", MESSAGE_TIMEOUT)
    
        # Forwards the message received onto the next stage in the process.
        def forward_event_to_output(self, outputQueueName, event, send_context):
            self.client.send_event_async(
                outputQueueName, event, send_confirmation_callback, send_context)
    
        def send_event_to_output(self, outputQueueName, event, send_context):
            self.client.send_event_async(outputQueueName, event, send_confirmation_callback, send_context)
    
    def main(protocol):
        try:
            hub_manager = HubManager(protocol)
            analyse(hub_manager)
            while True:
                time.sleep(1)
    
        except IoTHubError as iothub_error:
            print ( "Unexpected error %s from IoTHub" % iothub_error )
            return
        except KeyboardInterrupt:
            print ( "IoTHubModuleClient sample stopped" )
    
    if __name__ == '__main__':
        main(PROTOCOL)
    
  3. 開啟名為 requirements.txt 的檔案,並以下列內容取代其內容:

    azure-iothub-device-client==1.4.0.0b3
    opencv-python==3.3.1.11
    tensorflow==1.8.0
    pillow==5.1.0
    
  4. 開啟名為 deployment.template.json 的檔案,並依照下列指導方針取代其內容:

    1. 因為您將有自己的唯一 JSON 結構,因此您必須手動編輯它(而不是複製範例)。 若要簡化這項操作,請使用下圖作為指南。

    2. 看起來與您不同的區域,但您 不應該變更的區域會反白顯示黃色

    3. 您需要刪除的區段會反白顯示紅色。

    4. 請小心刪除正確的括弧,並移除逗號。

      此螢幕快照顯示代碼行 12 到 15、49 到 57,並以黃色圓形顯示第 67 行。代碼行 39 到 48,第 66 行會以紅色圓形。

    5. 已完成的 JSON 看起來應該像下圖(不過,您的唯一差異如下: username/password/module name/module references):

      顯示命令視窗的螢幕快照,其中包含已刪除圓圈的紅線。

  5. 開啟名為 Dockerfile.amd64 的檔案,並以下列內容取代其內容:

    FROM ubuntu:xenial
    
    WORKDIR /app
    
    RUN apt-get update && \
        apt-get install -y --no-install-recommends libcurl4-openssl-dev python-pip libboost-python-dev && \
        rm -rf /var/lib/apt/lists/* 
    RUN pip install --upgrade pip
    RUN pip install setuptools
    
    COPY requirements.txt ./
    RUN pip install -r requirements.txt
    
    RUN pip install pillow
    RUN pip install numpy
    
    RUN apt-get update && apt-get install -y \ 
        pkg-config \
        python-dev \ 
        python-opencv \ 
        libopencv-dev \ 
        libav-tools  \ 
        libjpeg-dev \ 
        libpng-dev \ 
        libtiff-dev \ 
        libjasper-dev \ 
        python-numpy \ 
        python-pycurl \ 
        python-opencv
    
    
    RUN pip install opencv-python
    RUN pip install tensorflow
    RUN pip install --upgrade tensorflow
    
    COPY . .
    
    RUN useradd -ms /bin/bash moduleuser
    USER moduleuser
    
    CMD [ "python", "-u", "./main.py" ]
    
    
  6. 以滑鼠右鍵按兩下模組下方的資料夾(它會有您先前提供的名稱;在下一個範例中,它稱為 pythonmodule),然後按下 [新增資料夾]。 將資料夾 映像命名為 。

  7. 在資料夾內,新增一些包含滑鼠或鍵盤的影像。 這些是 Tensorflow 模型將分析的影像。

    警告

    如果您使用自己的模型,您必須變更此專案,以反映您自己的模型數據。

  8. 您現在必須在第 1 章中,從您先前下載的 model 資料夾中擷取labels.txtmodel.pb 檔案(或從您自己的 自訂視覺 服務建立)。 一旦您擁有檔案,請將檔案放在解決方案中,並放在其他檔案中。 最終結果看起來應該像下圖:

    顯示 [總管] 視窗的螢幕快照。Python 模組資料夾已開啟。

第 9 章 - 將解決方案封裝為容器

  1. 您現在已準備好將檔案「封裝」為容器,並將其推送至您的 Azure Container Registry。 在 VS Code 中,開啟整合式終端機(檢視>整合式終端機或 Ctrl`+),並使用下列這一行來登入 Docker(以 Azure Container Registry (ACR)認證取代 命令的值):

        docker login -u <ACR username> -p <ACR password> <ACR login server>
    
  2. 以滑鼠右鍵按兩下 檔案deployment.template.json,然後按兩下 [ 建置IoT Edge解決方案]。 此建置程式需要相當長的時間(視您的裝置而定),因此請準備好等候。 建置程式完成之後,會在名為 config 的新資料夾內建立deployment.json檔案。

    顯示設定資料夾和部署點 jason 檔案以紅色圓圈的螢幕快照。

  3. 再次開啟命令選擇區,然後搜尋 Azure:登入。 使用您的 Azure 帳戶認證遵循提示;VS Code 會提供 [複製] 和 [開啟] 的選項,這會複製您很快就會需要的裝置程序代碼,並開啟預設網頁瀏覽器。 當系統詢問時,貼上裝置程式代碼以驗證您的計算機。

    複製並開啟

  4. 登入之後,您會注意到在 [探索] 面板底部,名為 [Azure IoT 中樞 裝置] 的新區段。 按兩下此區段展開。

    edge 裝置

  5. 如果您的裝置不是這裡,您必須以滑鼠右鍵按兩下 [Azure IoT 中樞 裝置],然後按兩下 [設定 IoT 中樞 連接字串]。 接著 ,您會看到命令選擇區 (VS Code 頂端),會提示您輸入 連接字串。 這是您在第 3 章結尾記下的連接字串一旦您複製字串之後,請按 Enter 鍵。

  6. 您的裝置應該載入並出現。 以滑鼠右鍵按兩下裝置名稱,然後按兩下 [ 建立單一裝置的部署]。

    顯示右鍵功能表的螢幕快照。已醒目提示 [建立單一裝置的部署]。

  7. 您將會收到 檔案總管 提示,您可以在其中流覽至 config 資料夾,然後選取deployment.json檔案。 選取該檔案后,按兩下 [ 選取Edge部署指令清單 ] 按鈕。

    顯示 [檔案總管] 視窗的螢幕快照。已選取部署點 jason 檔案,然後選取 [選取 Edge 部署指令清單] 會以紅色圓圈。

  8. 此時,您已提供您的 IoT 中樞 服務指令清單,以將容器部署為模組,從 Azure Container Registry 有效地將其部署至您的裝置。

  9. 若要檢視從裝置傳送至 IoT 中樞 的訊息,請在 [Azure IoT 中樞 裝置] 區段中,於 [總管] 面板中再次以滑鼠右鍵按兩下您的裝置名稱,然後按兩下 [開始監視 D2C 訊息]。 從裝置傳送的訊息應該會出現在 VS 終端機中。 耐心,因為這可能需要一些時間。 請參閱下一章以進行偵錯,並檢查部署是否成功。

此課程模組現在會在 images 資料夾中的 影像 之間逐一查看,並使用每個反覆專案加以分析。 這顯然只是示範如何讓基本的機器學習模型在IoT Edge裝置環境中運作。

若要擴充此範例的功能,您可以透過數種方式繼續進行。 其中一種方式可能是在容器中包含一些程式代碼,它會從聯機到裝置的網路攝影機擷取相片,並將影像儲存在images資料夾中。

另一種方式可能是將映像從IoT裝置複製到容器。 這樣做的實用方式是在IoT裝置終端機中執行下列命令(如果您想要將程式自動化,可能是小型應用程式可以執行此作業)。 您可以從儲存盤案的資料夾位置手動執行此指令來測試此指令:

    sudo docker cp <filename> <modulename>:/app/images/<a name of your choice>

第 10 章 - 偵錯 IoT Edge 運行時間

以下是命令行和秘訣清單,可協助您從Ubuntu裝置監視和偵錯IoT Edge運行時間傳訊活動。

  • 執行下列命令列來 檢查 IoT Edge 執行時間 狀態:

        sudo systemctl status iotedge
    

    注意

    請記得按 Ctrl + C,以完成檢視狀態。

  • 列出目前部署的容器。 如果 IoT 中樞 服務已成功部署容器,則會執行下列命令行來顯示這些容器:

        sudo iotedge list
    

    Or

        sudo docker ps
    

    注意

    上述是檢查模組是否已成功部署的好方法,因為它會出現在清單中;否則 ,您只會 看到 edgeHubedgeAgent

  • 若要顯示容器的程式代碼記錄,請執行下列命令列:

        journalctl -u iotedge
    

管理 IoT Edge 執行時間的實用命令:

  • 若要刪除主機中的所有容器:

        sudo docker rm -f $(sudo docker ps -aq)
    
  • 若要停止 IoT Edge 執行時間

        sudo systemctl stop iotedge
    

第 11 章 - 建立數據表服務

流覽回您的 Azure 入口網站,您將藉由建立記憶體資源來建立 Azure 數據表服務。

  1. 如果尚未登入,請登入 Azure 入口網站

  2. 登入之後,按兩下左上角的 [ 建立資源],然後搜尋 記憶體帳戶,然後按 Enter 鍵以開始搜尋。

  3. 出現之後,按兩下 清單中的 [記憶體帳戶 - Blob、檔案、資料表、佇列 ]。

    顯示 [新增] 視窗的螢幕快照。記憶體會在搜尋列中輸入。在 [精選] 底下,儲存體帳戶 Blob、檔案、數據表、佇列會以紅色圓形。

  4. 新頁面將提供記憶體帳戶服務的描述。 在此提示的左下角,按兩下 [ 建立] 按鈕,以建立此服務的實例。

    顯示記憶體帳戶頁面的螢幕快照。頁面底部的 [建立] 按鈕會以紅色圓形。

  5. 按兩下 [ 建立] 之後,會出現面板:

    1. 插入此服務實例所需的 名稱必須是全部小寫)。

    2. 針對 [部署模型],按兩下 [資源管理員]。

    3. 針對 [帳戶種類],使用下拉功能表,單擊 [ 記憶體] (一般用途 v1)

    4. 按兩下適當的 [位置]。

    5. 針對 [復寫] 下拉功能表,單擊 [讀取存取- 異地備援記憶體 ] [RA-GRS]。

    6. 針對 [效能],按兩下 [ 標準]。

    7. 在 [ 需要安全傳輸] 區段中,按兩下 [ 已停用]。

    8. 從 [ 訂用帳戶 ] 下拉功能表中,單擊適當的訂用帳戶。

    9. 選擇資源群組或建立新的群組。 資源群組提供一種方式來監視、控制存取、布建和管理 Azure 資產集合的計費。 建議將所有與單一專案相關聯的 Azure 服務(例如,例如這些課程)保留在通用資源群組下)。

      如果您想要深入瞭解 Azure 資源群組,請遵循此 連結以瞭解如何管理資源群組

    10. 如果這是您的選項,請將虛擬網路保留[已停用]。

    11. 按一下 [建立]。

      填入記憶體詳細數據

  6. 按兩下 [建立] 之後,您必須等候服務建立,這可能需要一分鐘的時間。

  7. 建立服務實例之後,入口網站中會出現通知。 按兩下通知以探索新的服務實例。

    新的記憶體通知

  8. 按兩下通知中的 [ 移至資源 ] 按鈕,系統會帶您前往新的記憶體服務實例概觀頁面。

    顯示部署成功通知的螢幕快照。[移至資源] 按鈕會以紅色圓圈。

  9. 從概觀頁面到右側,按兩下 [ 數據表]。

    資料表

  10. 右側的面板將會變更以顯示 資料表服務 資訊,其中您需要新增數據表。 按兩下左上角的 [ + 資料表] 按鈕即可執行此動作。

    開啟數據表

  11. 隨即會顯示新的頁面,其中您需要輸入 數據表名稱。 這是您將用來在稍後章節中參考應用程式中數據的名稱(建立函式應用程式和 Power BI)。 將 IoTMessages 插入為名稱(您可以選擇自己的名稱,只要記得本文稍後使用時),然後按兩下 [確定]。

  12. 建立新的資料表之後,您就可以在 [數據表服務 ] 頁面 (底部) 中看到它。

    顯示 [數據表服務] 頁面的螢幕快照,其中包含列出的數據表。

  13. 現在按下 [存取金鑰],並取得記憶體帳戶名稱和密鑰複本(使用記事本),您稍後會在建立 Azure 函式應用程式使用這些值。

    顯示 [存取金鑰] 頁面的螢幕快照,位於 [設定] 底下。[儲存體帳戶名稱] 字段和 [金鑰] 欄位會以紅色圓形。

  14. 再次使用左側面板,捲動至 [數據表服務] 區段,然後按兩下 [資料表] (或瀏覽數據表,位於較新的入口網站中),並取得數據表URL的複本(使用記事本)。 您將在此課程稍後使用此值,將資料表連結至 Power BI 應用程式。

    顯示 [數據表服務] 底下 [數據表] 頁面的螢幕快照。I O T 訊息數據表的 U R L 會以紅色圓形。

第 12 章 - 完成 Azure 數據表

現在已設定數據表 服務 記憶體帳戶,現在可以將數據加入其中,以用來儲存和擷取資訊。 您可以透過 Visual Studio 編輯資料表。

  1. 開啟 Visual Studio不是 Visual Studio Code)。

  2. 從功能表中,按兩下 [檢視>雲端總管]。

    開啟雲端總管

  3. 雲端總管會以固定專案的形式開啟(耐心,因為載入可能需要時間)。

    警告

    如果您用來建立記憶體 帳戶的訂用帳戶 不可見,請確定您具有:

    • 登入與您用於 Azure 入口網站的帳戶相同。

    • 從 [帳戶管理] 頁面選取您的訂用帳戶(您可能需要從您的帳戶設定套用篩選):

      尋找訂用帳戶

  4. 您的 Azure 雲端服務將會顯示。 尋找 [記憶體帳戶 ],然後按兩下該帳戶左側的箭號,展開您的帳戶。

    開啟記憶體帳戶

  5. 展開之後,您應該可以使用新建立的 記憶體帳戶 。 按兩下記憶體左側的箭號,然後展開之後,尋找 [資料表 ],然後按兩下該位置旁的箭號,以顯示 您在上一章中建立的數據表 。 按兩下您的 資料表

  6. 您的數據表將會在 Visual Studio 視窗的中央開啟。 按兩下具有 [加號] 的數據表圖示 +

    新增數據表

  7. 隨即會出現視窗,提示您新增 實體。 您只會建立一個實體,不過它會有三個屬性。 您會發現已提供 PartitionKey 和 RowKey,因為數據表會使用這些數據來尋找您的數據。

    數據分割和數據列索引鍵

  8. 更新下列值:

    • 名稱: PartitionKey,值: PK_IoTMessages

    • 名稱: RowKey、值: RK_1_IoTMessages

  9. 然後,按兩下 [新增屬性] [新增實體] 視窗左下角,然後新增下列屬性:

    • MessageContent,以字串的形式保留 Value 空白。
  10. 您的資料表應該符合下圖中的數據表:

    新增正確的值

    注意

    實體在數據列索引鍵中具有數位 1 的原因,是因為您可能想要新增更多訊息,而您應該進一步嘗試本課程。

  11. 完成時,請按一下 [確定]。 您的數據表現在已可供使用。

第 13 章 - 建立 Azure 函式應用程式

現在是時候建立 Azure 函式應用程式,IoT 中樞 服務會呼叫此應用程式,以將 IoT Edge 裝置訊息儲存您在上一章中建立的數據表服務中。

首先,您需要建立一個檔案,以允許 Azure 函式載入您需要的連結庫。

  1. 開啟 [記事本 ] (按 Windows 鍵,然後輸入 記事本)。

    開啟記事本

  2. 在 [記事本] 開啟時,將下面的 JSON 結構插入其中。 完成後,請將它儲存在桌面上作為 project.json。 此檔案會定義函式將使用的連結庫。 如果您已使用 NuGet,看起來會很熟悉。

    警告

    命名正確很重要;請確定它沒有 .txt 擴展名。 請參閱下方以取得參考:

    JSON 儲存

    {
    "frameworks": {
        "net46":{
        "dependencies": {
            "WindowsAzure.Storage": "9.2.0"
        }
        }
    }
    }
    
  3. 登入 Azure 入口網站

  4. 登入之後,按兩下左上角的 [ 建立資源 ],然後搜尋 [函式應用程式],然後按 Enter 鍵來搜尋。 按兩下結果中的 [ 函式應用程式 ],以開啟新的面板。

    搜尋函式應用程式

  5. 新的面板會提供函式App Service的描述。 按兩下此面板 左下方的 [建立 ] 按鈕,以建立與此服務的關聯。

    函式應用程式實例

  6. 按兩下 [建立] 之後,請填入下列內容:

    1. 針對 [ 應用程式名稱],插入此服務實例所需的名稱。

    2. 選取 [訂用帳戶]

    3. 選取適合您的定價層,如果這是第一次建立 函式 App Service,您應該可以使用免費層。

    4. 選擇資源群組或建立新的群組。 資源群組提供一種方式來監視、控制存取、布建和管理 Azure 資產集合的計費。 建議將所有與單一專案相關聯的 Azure 服務(例如,例如這些課程)保留在通用資源群組下)。

      如果您想要深入瞭解 Azure 資源群組,請遵循此 連結以瞭解如何管理資源群組

    5. 針對 OS,按兩下 [Windows],就如同預期平臺一樣。

    6. 選取主 控方案 (本教學課程使用取用 方案

    7. 選取 [位置] (選擇與您在上一個步驟中建置的記憶體相同的位置)

    8. 針對 [記憶體] 區段,您必須選取您在上一個步驟中建立的記憶體服務。

    9. 您不需要此應用程式中的 Application Insights,因此請放心將其關閉

    10. 按一下 [建立]。

      建立新的實例

  7. 按兩下 [建立] 之後,您必須等候服務建立,這可能需要一分鐘的時間。

  8. 建立服務實例之後,入口網站中會出現通知。

    新增通知

  9. 按兩下通知,一旦部署成功(已完成)。

  10. 按兩下通知中的 [ 移至資源 ] 按鈕,以探索新的服務實例。

    顯示 [部署成功通知] 視窗的螢幕快照。[移至資源] 按鈕會以紅色圓圈。

  11. 在新面板的左側,按兩下 + [函式] 旁的 [加號] 圖示,以建立新的函式。

    顯示 [函式應用程式] 頁面的螢幕快照。在 Functions 旁邊的左側功能表中,加號會以紅色圓圈。

  12. 在中央面板中, [函式 建立] 視窗隨即出現。 向下卷動,然後按兩下 [ 自定義函式]。

    顯示 [函式建立] 視窗底部的螢幕快照。自定義函式會以紅色圓形。

  13. 向下捲動下一頁,直到您找到 IoT 中樞 (事件中樞),然後按兩下它。

    顯示以紅色圓形顯示 I O T 中樞事件中樞方塊的螢幕快照。

  14. 在 [IoT 中樞 (事件中樞) 刀鋒視窗中,將 [語言] 設定為 C# ,然後按兩下 [新增]。

    顯示 [新增函式] 頁面的螢幕快照。在 [語言] 欄位中選取 C sharp。[事件中樞連線] 選項旁的紅色圓形新增 。

  15. 在出現的視窗中,請確定已選取 IoT 中樞,且 [IoT 中樞] 欄位的名稱會對應至您先前建立的 IoT 中樞 服務名稱在第 3 章的步驟 8 中)。 然後按下 [ 選取] 按鈕。

    顯示 [I O T 中樞] 索引標籤開啟的螢幕快照。I O T 中樞和端點字段會以紅色圓形。

  16. 回到 [IoT 中樞 [事件中樞] 刀鋒視窗,按兩下 [建立]。

    顯示 [新增函式] 頁面的螢幕快照。頁面底部的 [建立] 按鈕會以紅色圓形。

  17. 系統會將您重新導向至函式編輯器。

    顯示函式編輯器頁面的螢幕快照。函式會在左側功能表中選取。

  18. 刪除其中的所有程式代碼,並將它取代為下列專案:

    #r "Microsoft.WindowsAzure.Storage"
    #r "NewtonSoft.Json"
    
    using System;
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Table;
    using Newtonsoft.Json;
    using System.Threading.Tasks;
    
    public static async Task Run(string myIoTHubMessage, TraceWriter log)
    {
        log.Info($"C# IoT Hub trigger function processed a message: {myIoTHubMessage}");
    
        //RowKey of the table object to be changed
        string tableName = "IoTMessages";
        string tableURL = "https://iothubmrstorage.table.core.windows.net/IoTMessages";
    
        // If you did not name your Storage Service as suggested in the course, change the name here with the one you chose.
        string storageAccountName = "iotedgestor"; 
    
        string storageAccountKey = "<Insert your Storage Key here>";   
    
        string partitionKey = "PK_IoTMessages";
        string rowKey = "RK_1_IoTMessages";
    
        Microsoft.WindowsAzure.Storage.Auth.StorageCredentials storageCredentials =
            new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(storageAccountName, storageAccountKey);
    
        CloudStorageAccount storageAccount = new CloudStorageAccount(storageCredentials, true);
    
        // Create the table client.
        CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
    
        // Get a reference to a table named "IoTMessages"
        CloudTable messageTable = tableClient.GetTableReference(tableName);
    
        //Retrieve the table object by its RowKey
        TableOperation operation = TableOperation.Retrieve<MessageEntity>(partitionKey, rowKey);
        TableResult result = await messageTable.ExecuteAsync(operation);
    
        //Create a MessageEntity so to set its parameters
        MessageEntity messageEntity = (MessageEntity)result.Result;
    
        messageEntity.MessageContent = myIoTHubMessage;
        messageEntity.PartitionKey = partitionKey;
        messageEntity.RowKey = rowKey;
    
        //Replace the table appropriate table Entity with the value of the MessageEntity Ccass structure.
        operation = TableOperation.Replace(messageEntity);
    
        // Execute the insert operation.
        await messageTable.ExecuteAsync(operation);
    }
    
    // This MessageEntity structure which will represent a Table Entity
    public class MessageEntity : TableEntity
    {
        public string Type { get; set; }
        public string MessageContent { get; set; }   
    }
    
  19. 變更下列變數,使其對應至適當的值(數據表和記憶體值,分別來自第 11 章和第 11 章的步驟 13),您可以在記憶體帳戶中找到:

    • tableName,其名稱位於記憶體帳戶中的數據表
    • tableURL,具有您儲存體帳戶數據表的 URL。
    • storageAccountName,其值的名稱對應到記憶體 帳戶 名稱。
    • storageAccountKey,其中包含您先前在記憶體服務中取得的密鑰。

    顯示命令提示字元的螢幕快照。線條 15、16、19 和 21 會以紅色圓形。

  20. 在程式代碼就緒后,按兩下 [ 儲存]。

  21. 接下來,按下 < 頁面右側的 [箭號] 圖示。

    顯示 [函式應用程式] 頁面的螢幕快照。

  22. 面板會從右側滑入。 在該面板中,按兩下 [上傳],[ 檔案瀏覽器 ] 隨即出現。

  23. 流覽至先前在 [記事本] 中建立的project.json檔案,然後按兩下 [開啟] 按鈕。 此檔案會定義函式將使用的連結庫。

    此螢幕快照顯示 [檢視檔案] 底下的紅色圓形上傳按鈕。在 [檔案瀏覽器] 中,已選取專案點 jason。

  24. 檔案上傳後,它會出現在右側的面板中。 按兩下會在函 編輯器開啟它。 它看起來必須與下一個影像完全相同。

    顯示 [函式應用程式] 頁面的螢幕快照。左側功能表中的 [整合] 會以紅色圓形顯示。

  25. 此時,測試函式將訊息儲存在數據表的能力是很好的。 在視窗右上方,按兩下 [ 測試]。

    顯示 [函式應用程式] 頁面的螢幕快照。在右上方進行測試,左下角的 [執行] 按鈕會以紅色圓圈。

  26. 在要求本文插入訊息,如下圖所示,然後按兩下 [執行]。

  27. 函式會執行,顯示結果狀態(您會在 [輸出] 視窗上方看到綠色的 [已接受狀態 202],這表示它是成功的呼叫):

    輸出結果

第 14 章 - 檢視作用中的訊息

如果您現在開啟 Visual Studio (而非 Visual Studio Code),您可以將測試訊息結果可視化,因為它會儲存在 MessageContent 字串區域中。

顯示 Visual Studio Microsoft 中開啟 [I O T 訊息數據表] 索引標籤的螢幕快照。

已就地使用數據表服務和函式應用程式,您的 Ubuntu 裝置訊息會出現在 IoTMessages 資料表中。 如果尚未執行,請再次啟動您的裝置,而且您將能夠透過使用 Visual Studio Cloud Explorer,在您的資料表內查看來自裝置和模組的結果訊息。

將數據可視化

第 15 章 - Power BI 設定

若要將 IOT 裝置的數據可視化,您將設定 Power BI (桌面版本),以從您剛才建立的 數據表 服務收集數據。 Power BI 的 HoloLens 版本接著會使用該數據將結果可視化。

  1. 開啟 Windows 10 上的 Microsoft Store 並搜尋Power BI Desktop

    顯示 [Microsoft市集] 視窗的螢幕快照。Power B I 在搜尋列中輸入,Power B I Desktop 會以紅色圓形。

  2. 下載應用程式。 完成下載之後,請開啟它。

  3. 使用您的 Microsoft 365 帳戶登入 Power BI。 您可能會重新導向至瀏覽器,以註冊。 註冊之後,請返回 Power BI 應用程式,然後再次登入。

  4. 按兩下 [ 取得數據 ],然後按兩下 [ 更多...]。

    顯示Power B I Desktop 的螢幕快照。[取得數據] 下拉功能表中的 [更多] 會以紅色圓形。

  5. 按兩下 [Azure]、[Azure 資料表記憶體],然後按兩下 [連線]。

    顯示 [取得資料] 視窗的螢幕快照。在 [Azure] 選單選項中選取 [Azure 數據表記憶體]。右下角的 [連接] 按鈕會以紅色圓形。

  6. 系統會提示您在建立數據表服務時插入 您稍早收集的數據表 URL在第 11 章的步驟 13 中)。 插入 URL 之後,請刪除參考資料表 「sub-folder」 的路徑部分(在此課程中為 IoTMessages)。 最終結果應如下圖所示。 接著按一下 [確定]。

    顯示 [Azure 資料表記憶體] 對話框的螢幕快照。[帳戶名稱] 或 [U R L] 欄位中輸入 U R L。

  7. 系統會提示您在建立資料表記憶體時插入 您記下的記憶體密鑰在第 11 章的步驟 11 中)。 然後按兩下 [ 連線]。

    顯示 Azure 資料表記憶體帳戶金鑰頁面的螢幕快照。

  8. 隨即會顯示 [導覽器面板],勾選 [數據表] 旁的方塊,然後按兩下 [載入]。

    顯示 [導覽器] 面板的螢幕快照。核取 I O T 訊息檔案旁的方塊。

  9. 您的數據表現在已載入 Power BI,但需要查詢才能顯示其中的值。 若要這樣做,請以滑鼠右鍵按下位於 畫面右側 [字段] 面板 的數據表名稱。 然後按兩下 [ 編輯查詢]。

    顯示 [欄位] 面板的螢幕快照。[I O T 訊息] 右鍵功能表中的 [編輯查詢] 會以紅色圓形。

  10. Power Query 編輯器 會以新視窗開啟,並顯示您的資料表。 按兩下資料表 [內容] 資料行內的 [記錄] 一字,即可將儲存的內容可視化。

    顯示 Power Query 編輯器 視窗的螢幕快照。在 [內容] 底下,[記錄] 會以紅色圓圈。

  11. 按兩下視窗左上方的 [進入資料表]。

    顯示 Power Query 編輯器 中 [轉換] 索引標籤的螢幕快照。在左上角,Into Table 會以紅色圓圈。

  12. 按兩下 [ 關閉並套用]。

    顯示 Power Query 編輯器 中首頁索引標籤的螢幕快照。Close 和 Apply 會以紅色圓圈。

  13. 在查詢完成載入之後,在畫面右側的 FIELDS 面板中,勾選對應至 [名稱] 和 [值] 參數的方塊,以可視化顯示 MessageContent 數據行內容。

    顯示 [欄位] 面板的螢幕快照。在 [I O T 訊息] 底下,會檢查 [名稱] 和 [值]。[名稱] 和 [值] 資料行的彈出視窗會以紅色圓圈。

  14. 按兩下視窗左上方的藍色磁碟圖示,將工作儲存在您選擇的資料夾中。

    顯示Power B I Desktop 的螢幕快照。左上角的藍色磁碟會以紅色圓圈。[另存新檔] 對話框隨即開啟,[儲存] 按鈕會以紅色圓圈。

  15. 您現在可以按兩下 [發佈] 按鈕,將數據表上傳至工作區。 出現提示時,按兩下 [我的工作區 ],然後按兩下 [ 選取]。 等候它顯示提交的成功結果。

    顯示以紅色圓形發佈的螢幕快照。在 [發佈至 Power B I] 對話框中,選取 [選取目的地] 底下的 [我的工作區]。

    顯示通知的螢幕快照,指出發佈至 Power B 我成功。

警告

下列章節是 HoloLens 專屬的。 Power BI 目前無法作為沉浸式應用程式使用,不過,您可以透過傳統型應用程式,在 Windows Mixed Reality Portal (也稱為 Cliff House) 中執行桌面版本。

第 16 章 - 在 HoloLens 上顯示 Power BI 數據

  1. 在您的 HoloLens 上,點選應用程式清單中的圖示,以登入 Microsoft Store

    Holo Lens 顯示導覽視窗中Microsoft市集圖示周圍的紅色圓圈。

  2. 搜尋並下載 Power BI 應用程式。

    顯示 [Microsoft市集] 頁面的 Holo Lens 顯示。已選取卷動工具,並在搜尋列中輸入電源 B I。

  3. 從您的應用程式清單中啟動 Power BI

  4. Power BI 可能會要求您登入 Microsoft 365 帳戶

  5. 在應用程式內之後,工作區預設應該會顯示,如下圖所示。 如果沒有發生,只要按兩下視窗左側的工作區圖示即可。

    Holo Lens 顯示Microsoft Power B I 頁面。拖曳工具已選取頂端。類似於圖形的工作區圖示會以紅色圓形。報表底下的 I O T Edge 數據表會以紅色圓形。

您已完成 IoT 中樞 應用程式

恭喜您,您已成功使用仿真的虛擬機 Edge 裝置建立 IoT 中樞 服務。 您的裝置可以將機器學習模型的結果傳達給 Azure 資料表服務,由 Azure 函式應用程式協助,此應用程式會讀取 Power BI,並在 Microsoft HoloLens 內可視化。

Holo Lens 顯示Microsoft Power B I 頁面。

額外練習

練習 1

展開儲存在數據表中的傳訊結構,並將其顯示為圖形。 您可能想要收集更多數據,並將其儲存在相同的數據表中,以供稍後顯示。

練習 2

建立要部署在IoT面板上的其他「相機擷取」模組,以便透過相機擷取影像以進行分析。