Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
V tomto návodu se naučíte používat službu Azure Web PubSub a Azure Functions k vytvoření bezserverové aplikace s vizualizací dat v reálném čase z IoT Hubu.
V tomto návodu se naučíte, jak:
- Vytvoření aplikace pro vizualizaci dat bez serveru
- Spolupráce se vstupními a výstupními vazbami funkce Web PubSub a Azure IoT Hubem
- Spusťte ukázkové funkce lokálně
Důležité
Nespracované připojovací řetězce se v tomto článku zobrazují pouze pro demonstrační účely.
Připojovací řetězec obsahuje informace o autorizaci potřebné pro to, aby vaše aplikace měla přístup ke službě Azure Web PubSub. Přístupový klíč uvnitř připojovacího řetězce je podobný kořenovému heslu pro vaši službu. V produkčním prostředí vždy chraňte své přístupové klíče. Použijte Azure Key Vault k bezpečné správě a rotaci klíčů a zabezpečte své připojení pomocí WebPubSubServiceClient.
Vyhněte se poskytování přístupových klíčů jiným uživatelům, jejich pevné kodování nebo ukládání kdekoli v prostém textu, který je přístupný ostatním. Otočte klíče, pokud se domníváte, že mohly být ohroženy.
Požadavky
Editor kódu, například Visual Studio Code
Node.js verze 18.x nebo vyšší.
Poznámka
Pro více informací o podporovaných verzích Node.js si přečtěte dokumentaci k verzím runtime Azure Functions.
Azure Functions Core Tools (preferováno v3 nebo vyšší) pro lokální spuštění aplikací Azure Function a jejich nasazení do Azure.
Nástroj Azure CLI pro správu prostředků Azure.
Pokud nemáte účet Azure, vytvořte si bezplatný účet před tím, než začnete.
Vytvořte IoT hub
V této sekci použijete Azure CLI k vytvoření IoT hubu a skupiny prostředků. Skupina prostředků Azure je logický kontejner, do kterého se nasazují a spravují prostředky Azure. IoT hub funguje jako centrální uzel pro oboustrannou komunikaci mezi vaší IoT aplikací a zařízeními.
Pokud už ve svém předplatném Azure máte centrum IoT, můžete tuto část přeskočit.
K vytvoření centra IoT a skupiny prostředků:
Spusťte aplikaci příkazového řádku (CLI). K provedení příkazů CLI ve zbytku tohoto článku zkopírujte syntaxi příkazu, vložte ji do své aplikace CLI, upravte hodnoty proměnných a stiskněte
Enter.- Pokud používáte Cloud Shell, vyberte tlačítko Vyzkoušet u příkazů CLI pro spuštění Cloud Shell ve složeném okně prohlížeče. Nebo můžete otevřít Cloud Shell v samostatné záložce prohlížeče.
- Pokud používáte Azure CLI místně, spusťte svou konzolovou aplikaci CLI a přihlaste se do Azure CLI.
Spusťte az extension add, abyste nainstalovali nebo upgradovali rozšíření azure-iot na aktuální verzi.
az extension add --upgrade --name azure-iotV aplikaci CLI spusťte příkaz az group create k vytvoření skupiny prostředků. Následující příkaz vytvoří skupinu prostředků s názvem MyResourceGroup na místě eastus.
Poznámka
Případně můžete nastavit jinou polohu. Pro zobrazení dostupných umístění spusťte
az account list-locations. V tomto rychlém startu se používá eastus , jak je znázorněno v ukázkovém příkazu.az group create --name MyResourceGroup --location eastusSpusťte příkaz az iot hub create k vytvoření IoT centra. Může trvat několik minut, než se vytvoří centrum IoT.
YourIoTHubName. Nahraďte tuto zástupnou hodnotu a okolní složené závorky v následujícím příkazu pomocí názvu, který jste si vybrali pro váš IoT hub. Název IoT hubu musí být v Azure globálně jedinečný. Použijte název svého IoT hubu v celé této úvodní příručce, kdykoli uvidíte zástupný symbol.
az iot hub create --resource-group MyResourceGroup --name {YourIoTHubName}
Vytvořte instanci Web PubSub
Pokud už ve svém předplatném Azure máte instanci Web PubSub, můžete tuto část přeskočit.
Spusťte az extension add k instalaci nebo upgradu rozšíření webpubsub na aktuální verzi.
az extension add --upgrade --name webpubsub
K vytvoření Web PubSub ve vámi vytvořené skupině prostředků použijte příkaz Azure CLI az webpubsub create. Následující příkaz vytvoří prostředek Web PubSub v úrovni Free ve skupině prostředků myResourceGroup v oblasti EastUS:
Důležité
Každý prostředek Web PubSub musí mít jedinečný název. Nahraďte <your-unique-resource-name> názvem vaší Web PubSub v následujících příkladech.
az webpubsub create --name "<your-unique-resource-name>" --resource-group "myResourceGroup" --location "EastUS" --sku Free_F1
Výstup tohoto příkazu ukazuje vlastnosti nově vytvořeného zdroje. Všimněte si dvou vlastností uvedených níže:
-
Název zdroje: Název, který jste zadali do výše uvedeného parametru
--name. -
hostName: V příkladu je
<your-unique-resource-name>.webpubsub.azure.com/název hostitele .
V tuto chvíli je váš účet Azure jediný, který má povolení provádět jakékoli operace s tímto novým zdrojem.
Vytvořte a spusťte funkce lokálně
Vytvořte prázdnou složku pro projekt a poté spusťte následující příkaz v nové složce.
func init --worker-runtime javascript --model V4Vytvořte funkci
indexpro čtení a hostování statické webové stránky pro klienty.func new -n index -t HttpTriggerAktualizujte
src/functions/index.jsnásledujícím kódem, který poskytuje HTML obsah jako statický web.const { app } = require('@azure/functions'); const { readFile } = require('fs/promises'); app.http('index', { methods: ['GET', 'POST'], authLevel: 'anonymous', handler: async (context) => { const content = await readFile('index.html', 'utf8', (err, data) => { if (err) { context.err(err) return } }); return { status: 200, headers: { 'Content-Type': 'text/html' }, body: content, }; } });Vytvořte soubor
index.htmlv kořenové složce.<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0/dist/Chart.min.js" type="text/javascript" charset="utf-8"></script> <script> document.addEventListener("DOMContentLoaded", async function (event) { const res = await fetch(`/api/negotiate?id=${1}`); const data = await res.json(); const webSocket = new WebSocket(data.url); class TrackedDevices { constructor() { // key as the deviceId, value as the temperature array this.devices = new Map(); this.maxLen = 50; this.timeData = new Array(this.maxLen); } // Find a device temperature based on its Id findDevice(deviceId) { return this.devices.get(deviceId); } addData(time, temperature, deviceId, dataSet, options) { let containsDeviceId = false; this.timeData.push(time); for (const [key, value] of this.devices) { if (key === deviceId) { containsDeviceId = true; value.push(temperature); } else { value.push(null); } } if (!containsDeviceId) { const data = getRandomDataSet(deviceId, 0); let temperatures = new Array(this.maxLen); temperatures.push(temperature); this.devices.set(deviceId, temperatures); data.data = temperatures; dataSet.push(data); } if (this.timeData.length > this.maxLen) { this.timeData.shift(); this.devices.forEach((value, key) => { value.shift(); }) } } getDevicesCount() { return this.devices.size; } } const trackedDevices = new TrackedDevices(); function getRandom(max) { return Math.floor((Math.random() * max) + 1) } function getRandomDataSet(id, axisId) { return getDataSet(id, axisId, getRandom(255), getRandom(255), getRandom(255)); } function getDataSet(id, axisId, r, g, b) { return { fill: false, label: id, yAxisID: axisId, borderColor: `rgba(${r}, ${g}, ${b}, 1)`, pointBoarderColor: `rgba(${r}, ${g}, ${b}, 1)`, backgroundColor: `rgba(${r}, ${g}, ${b}, 0.4)`, pointHoverBackgroundColor: `rgba(${r}, ${g}, ${b}, 1)`, pointHoverBorderColor: `rgba(${r}, ${g}, ${b}, 1)`, spanGaps: true, }; } function getYAxy(id, display) { return { id: id, type: "linear", scaleLabel: { labelString: display || id, display: true, }, position: "left", }; } // Define the chart axes const chartData = { datasets: [], }; // Temperature (ºC), id as 0 const chartOptions = { responsive: true, animation: { duration: 250 * 1.5, easing: 'linear' }, scales: { yAxes: [ getYAxy(0, "Temperature (ºC)"), ], }, }; // Get the context of the canvas element we want to select const ctx = document.getElementById("chart").getContext("2d"); chartData.labels = trackedDevices.timeData; const chart = new Chart(ctx, { type: "line", data: chartData, options: chartOptions, }); webSocket.onmessage = function onMessage(message) { try { const messageData = JSON.parse(message.data); console.log(messageData); // time and either temperature or humidity are required if (!messageData.MessageDate || !messageData.IotData.temperature) { return; } trackedDevices.addData(messageData.MessageDate, messageData.IotData.temperature, messageData.DeviceId, chartData.datasets, chartOptions.scales); const numDevices = trackedDevices.getDevicesCount(); document.getElementById("deviceCount").innerText = numDevices === 1 ? `${numDevices} device` : `${numDevices} devices`; chart.update(); } catch (err) { console.error(err); } }; }); </script> <style> body { font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; padding: 50px; margin: 0; text-align: center; } .flexHeader { display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: space-between; } #charts { display: flex; flex-direction: row; flex-wrap: wrap; justify-content: space-around; align-content: stretch; } .chartContainer { flex: 1; flex-basis: 40%; min-width: 30%; max-width: 100%; } a { color: #00B7FF; } </style> <title>Temperature Real-time Data</title> </head> <body> <h1 class="flexHeader"> <span>Temperature Real-time Data</span> <span id="deviceCount">0 devices</span> </h1> <div id="charts"> <canvas id="chart"></canvas> </div> </body> </html>Vytvořte funkci
negotiate, kterou klienti používají k získání URL služby a přístupového tokenu.func new -n negotiate -t HttpTriggerAktualizujte
src/functions/negotiate.js, aby používalWebPubSubConnection, který obsahuje vygenerovaný token.const { app, input } = require('@azure/functions'); const connection = input.generic({ type: 'webPubSubConnection', name: 'connection', hub: '%hubName%' }); app.http('negotiate', { methods: ['GET', 'POST'], authLevel: 'anonymous', extraInputs: [connection], handler: async (request, context) => { return { body: JSON.stringify(context.extraInputs.get('connection')) }; }, });Vytvořte funkci
messagehandlerpro generování oznámení s použitím šablony"IoT Hub (Event Hub)".Nespracované připojovací řetězce se v tomto článku zobrazují pouze pro demonstrační účely. V produkčním prostředí vždy chraňte své přístupové klíče. Použijte Azure Key Vault k bezpečné správě a rotaci klíčů a zabezpečte své připojení pomocí
WebPubSubServiceClient.func new --template "Azure Event Hub trigger" --name messagehandlerAktualizujte
src/functions/messagehandler.jsa přidejte výstupní vazbu Web PubSub s následujícím kódem JSON. Používáme proměnnou%hubName%jako název hubu pro IoT eventHubName i pro Web PubSub hub.const { app, output } = require('@azure/functions'); const wpsAction = output.generic({ type: 'webPubSub', name: 'action', hub: '%hubName%' }); app.eventHub('messagehandler', { connection: 'IOTHUBConnectionString', eventHubName: '%hubName%', cardinality: 'many', extraOutputs: [wpsAction], handler: (messages, context) => { var actions = []; if (Array.isArray(messages)) { context.log(`Event hub function processed ${messages.length} messages`); for (const message of messages) { context.log('Event hub message:', message); actions.push({ actionName: "sendToAll", data: JSON.stringify({ IotData: message, MessageDate: message.date || new Date().toISOString(), DeviceId: message.deviceId, })}); } } else { context.log('Event hub function processed message:', messages); actions.push({ actionName: "sendToAll", data: JSON.stringify({ IotData: message, MessageDate: message.date || new Date().toISOString(), DeviceId: message.deviceId, })}); } context.extraOutputs.set(wpsAction, actions); } });
Aktualizujte nastavení funkce.
Přidejte
hubNamenastavení a nahraďte{YourIoTHubName}názvem centra, který jste použili při vytváření svého IoT Hubu.func settings add hubName "{YourIoTHubName}"Získejte připojovací řetězec služby pro IoT Hub.
az iot hub connection-string show --policy-name service --hub-name {YourIoTHubName} --output table --default-eventhubNastavte
IOTHubConnectionString, nahraďte<iot-connection-string>hodnotou.func settings add IOTHubConnectionString "<iot-connection-string>"- Získejte připojovací řetězec pro Web PubSub.
az webpubsub key show --name "<your-unique-resource-name>" --resource-group "<your-resource-group>" --query primaryConnectionStringNastavte
WebPubSubConnectionString, nahraďte<webpubsub-connection-string>hodnotou.func settings add WebPubSubConnectionString "<webpubsub-connection-string>"Poznámka
Funkce
Azure Event Hub triggerpoužitá v příkladu závisí na Azure Storage, ale můžete použít emulátor místního úložiště, když funkce běží lokálně. Pokud se zobrazí například chybaThere was an error performing a read operation on the Blob Storage Secret Repository. Please ensure the 'AzureWebJobsStorage' connection string is valid., budete si muset stáhnout a povolit emulátor úložiště.Spusťte funkci lokálně.
Teď můžete místní funkci spustit pomocí následujícího příkazu.
func startMůžete navštívit statickou stránku svého místního hostitele návštěvou:
https://localhost:7071/api/index.
Spusťte zařízení, abyste odeslali data
Zaregistrujte zařízení
Zařízení musí být zaregistrováno ve vašem IoT centru, než se může připojit. Pokud již máte zařízení registrované ve svém IoT hubu, můžete tuto část přeskočit.
Spusťte příkaz az iot hub device-identity create v Azure Cloud Shell k vytvoření identity zařízení.
YourIoTHubName: Nahraďte tento zástupný text názvem, který jste vybrali pro svůj IoT hub.
az iot hub device-identity create --hub-name {YourIoTHubName} --device-id simDeviceSpusťte příkaz Az PowerShell module iot hub device-identity connection-string show v Azure Cloud Shell, abyste získali řetězec připojení zařízení pro zařízení, které jste právě zaregistrovali.
YourIoTHubName: Nahraďte níže uvedený zástupný text názvem, který jste vybrali pro své IoT centrum.
az iot hub device-identity connection-string show --hub-name {YourIoTHubName} --device-id simDevice --output tablePoznamenejte si připojovací řetězec zařízení, který vypadá takto:
HostName={YourIoTHubName}.azure-devices.net;DeviceId=simDevice;SharedAccessKey={YourSharedAccessKey}
Pro dosažení nejrychlejších výsledků simulujte teplotní data pomocí Raspberry Pi Azure IoT Online Simulator. Vložte řetězec pro připojení zařízení a stiskněte tlačítko Spustit.
Pokud máte fyzický senzor Raspberry Pi a BME280, můžete měřit a hlásit skutečné hodnoty teploty a vlhkosti pomocí kurzu Připojení Raspberry Pi k Azure IoT Hubu (Node.js).
Spusťte vizualizační web
Otevřete indexovou stránku hostitele funkcí: http://localhost:7071/api/index pro zobrazení dashboardu v reálném čase. Zaregistrujte více zařízení a uvidíte, jak se v reálném čase aktualizuje panel s více zařízeními. Otevřete několik prohlížečů a uvidíte, že každá stránka je aktualizována v reálném čase.
Vyčistit zdroje
Pokud chcete pokračovat v práci s dalšími rychlými návody a kurzy, můžete chtít tyto prostředky zachovat.
Když již není potřeba, můžete použít příkaz az group delete v Azure CLI k odstranění skupiny prostředků a všech souvisejících zdrojů.
az group delete --name "myResourceGroup"