[英]Retrieve IoT Hub Twin from ServiceBus triggered azure function
我們正在將數據從IoT設備發送到Azure IoT中心,並嘗試將某種類型的消息傳遞給Azure功能。
現在,我們通過創建一個Azure Service Bus終結點並在IoTHub中創建一個消息路由來做到這一點。 它可以按預期工作,Azure功能可以正確接收消息。
現在,我們想從Azure功能中的IoT中心獲取DeviceId ,以及在Device Twin中定義的標簽 ,而我完全不知道該怎么做。
如果我們使用EventHubTrigger
,那么看起來很簡單,就像這樣:
public static class Test
{
[FunctionName("TestQueueTrigger")]
public static void Run(
[EventHubTrigger("messages/events", Connection = "IoTHubConnection")]
EventData message,
Twin deviceTwin,
TraceWriter log)
{ ... }
}
但是,實際上還不清楚如何使用Service Bus觸發器來完成此操作。
另外,我們希望將所有消息(獨立於路由)存儲到Azure Data Lake存儲中,而我對如何工作有點迷惑。
此處介紹了 Azure IoT中心設備到雲的消息格式。 此格式沒有設備孿生屬性。 設備雙胞胎存儲在雲后端,可以根據到特定終結點(內置和/或自定義終結點)的物聯網集線器路由來通知它們的更改。
您的函數“ TestQueueTrigger ”示例對版本1使用azure-functions-iothub-extension 。擴展輸入綁定Twin允許使用擴展內的單獨調用來獲取設備twin:
deviceTwin = await registryManager.GetTwinAsync(attribute.DeviceId);
基本上,此擴展也可以用於ServiceBusTrigger綁定。 請注意,此擴展只能用於功能版本1,因此,我建議使用例如REST API Get Twin調用在功能中獲取設備孿生。
更新
以下代碼片段顯示了ServiceBusTrigger函數和REST API Get Twin調用的示例。
run.csx文件:
#r "..\\bin\\Microsoft.Azure.ServiceBus.dll"
#r "..\\bin\\Microsoft.Azure.Devices.Shared.dll"
#r "Microsoft.Azure.WebJobs.ServiceBus"
#r "Newtonsoft.Json"
using System;
using System.Threading.Tasks;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.Azure.WebJobs.ServiceBus;
using Microsoft.Azure.ServiceBus;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Web;
using Microsoft.Azure.Devices.Shared;
// reusable proxy
static HttpClientHelper iothub = new HttpClientHelper(Environment.GetEnvironmentVariable("AzureIoTHubShariedAccessPolicy"));
public static async Task Run(Message queueItem, ILogger log)
{
// payload
log.LogInformation($"C# ServiceBus queue trigger function processed message: {Encoding.UTF8.GetString(queueItem.Body)}");
// device identity Id
var deviceId = queueItem.UserProperties["iothub-connection-device-id"];
// get the device twin
var response = await iothub.Client.GetAsync($"/twins/{deviceId}?api-version=2018-06-30");
response.EnsureSuccessStatusCode();
Twin twin = await response.Content.ReadAsAsync<Twin>();
log.LogInformation(JsonConvert.SerializeObject(twin.Tags, Formatting.Indented));
await Task.CompletedTask;
}
// helpers
class HttpClientHelper
{
HttpClient client;
DateTime expiringSaS;
(string hostname, string keyname, string key) config;
public HttpClientHelper(string connectionString)
{
config = GetPartsFromConnectionString(connectionString);
client = new HttpClient() { BaseAddress = new Uri($"https://{config.hostname}")};
SetAuthorizationHeader();
}
public HttpClient Client
{
get
{
if (expiringSaS < DateTime.UtcNow.AddMinutes(-1))
{
SetAuthorizationHeader();
}
return client;
}
}
internal void SetAuthorizationHeader()
{
lock (client)
{
if (expiringSaS < DateTime.UtcNow.AddMinutes(-1))
{
string sasToken = GetSASToken(config.hostname, config.key, config.keyname, 1);
if (client.DefaultRequestHeaders.Contains("Authorization"))
client.DefaultRequestHeaders.Remove("Authorization");
client.DefaultRequestHeaders.Add("Authorization", sasToken);
expiringSaS = DateTime.UtcNow.AddHours(1);
}
}
}
internal (string hostname, string keyname, string key) GetPartsFromConnectionString(string connectionString)
{
var parts = connectionString.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Split(new[] { '=' }, 2)).ToDictionary(x => x[0].Trim(), x => x[1].Trim());
return (parts["HostName"] ?? "", parts["SharedAccessKeyName"] ?? "", parts["SharedAccessKey"] ?? "");
}
internal string GetSASToken(string resourceUri, string key, string keyName = null, uint hours = 24)
{
var expiry = GetExpiry(hours);
string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = String.Format(CultureInfo.InvariantCulture, $"SharedAccessSignature sr={HttpUtility.UrlEncode(resourceUri)}&sig={HttpUtility.UrlEncode(signature)}&se={expiry}");
if (!string.IsNullOrEmpty(keyName))
sasToken += $"&skn={keyName}";
return sasToken;
}
internal string GetExpiry(uint hours = 24)
{
TimeSpan sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
return Convert.ToString((int)sinceEpoch.TotalSeconds + 3600 * hours);
}
}
function.json:
{
"bindings": [
{
"name": "queueItem",
"type": "serviceBusTrigger",
"direction": "in",
"queueName": "myQueue",
"connection": "myConnectionString_SERVICEBUS"
}
]
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.