Отправка сообщения Cloud-to-Device на устройства, предоставляемые через IoT-central

Я читал документацию этого нового предложения SaaS, но я не вижу упоминания о возможности отправки сообщения на устройство, например: для включения / выключения оборудования.

https://docs.microsoft.com/en-us/azure/iot-central/tutorial-add-device

Я вижу, что есть возможность изменить настройки устройства, так как можно изменить устройство-близнец. Также я читал, что есть способ отправить "эхо" на устройство. Но они не служат моей точной цели.

Итак, есть ли способ, которым я могу отправить сообщение C2D, используя строку подключения, которая может быть построена с помощью рутины? https://docs.microsoft.com/en-us/azure/iot-central/tutorial-add-device

Я хотел бы отправить этот C2D через AzureFunction, но было бы полезно узнать, можно ли его каким-либо образом интегрировать в интерфейс IoT-Central.

Любые другие входы для достижения моих требований (включите / выключите оборудование) также будут очень полезны!

Спасибо и всего наилучшего,

3 ответа

Как я упоминал в своем комментарии, Azure IoT Central полностью контролирует внутреннюю конечную точку, обращенную к службе IoT Hub. Однако есть способ, при котором Azure IoT Central разрешает ограниченный доступ к этой конечной точке, ориентированной на службы, и использует REST API для обработки двойника устройства и вызова прямого метода на устройстве.

Ниже приведены инструкции по получению токена sas для заголовка авторизации, необходимого для вызовов REST Api:

  1. Получите токен доступа из приложения Azure IoT Central.

    формат такой:

    SharedAccessSignature sr=appId&sig=xxxxx&skn=myTokenName&se=1577730019340
    

    Обратите внимание, что appId показывает идентификатор вашего приложения Azure IoT Central

  2. Вызовите запрос REST POST, чтобы получить iothubTenantSasToken.sasToken

    POST https://api.azureiotcentral.com/v1-beta/applications/{appId}/diagnostics/sasTokens  
    Authorization:SharedAccessSignature sr=appId&sig=xxxxx&skn=myTokenName&se=1577730019340
    

    Ответ имеет следующий формат:

    {
      "iothubTenantSasToken": {
        "sasToken": "SharedAccessSignature sr=saas-iothub-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net&sig=xxxxx&se=1546197703&skn=service"
        },
      "eventhubSasToken": {
        "sasToken": "SharedAccessSignature sr=sb%3A%2F%2Fep-ns-saas-ep-15-262-xxxxxxxxxx.servicebus.windows.net%2Fep-ehub-saas-iothu-1044564-xxxxxxxxxx&sig=xxxxxx&se=1546197703&skn=service",
        "entityPath": "ep-ehub-saas-iothu-1044564-xxxxxxxxxx",
        "hostname": "sb://ep-ns-saas-ep-15-262-xxxxxxxxxx.servicebus.windows.net/"
        },
      "expiry": 1546197703
    }
    
  3. SasToken для наших обращающихся к сервису вызовов конечной точки:

    SharedAccessSignature sr=saas-iothub-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net&sig=xxxxx&se=1546197703&skn=service
    

Теперь мы можем использовать некоторые API REST-концентратора Azure IoT, в основном вызовы с двойниками в пути uri, такие как:

https://docs.microsoft.com/en-us/rest/api/iothub/service/gettwin

https://docs.microsoft.com/en-us/rest/api/iothub/service/updatetwin

https://docs.microsoft.com/en-us/rest/api/iothub/service/replacetwin

https://docs.microsoft.com/en-us/rest/api/iothub/service/invokedevicemethod

Пример вызова прямого метода на устройстве1:

POST https://saas-iothub-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net/twins/device1/methods?api-version=2018-06-30
Authorization:SharedAccessSignature sr=saas-iothub-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net&sig=xxxxx&se=1546197703&skn=service

body:
    {
      "methodName": "writeLine",
      "timeoutInSeconds": 20,
      "payload": {
         "input1": 12345,
         "input2": "HelloDevice"
         }
    }

Пример обновления свойства двойных тегов устройства:

PATCH https://saas-iothub-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net/twins/device1?api-version=2018-06-30
Authorization:SharedAccessSignature sr=saas-iothub-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.azure-devices.net&sig=xxxxx&se=1546197703&skn=service

body:
    {
      "tags": {
        "test":12345
        }
    }

Обратите внимание, что срок действия sasToken составляет 60 минут. Я рекомендую кешировать объект ответа с шага 2. и обновлять в зависимости от времени истечения.

ОБНОВИТЬ:

Далее приведены шаги по использованию токена доступа IoT Central для обработки двойников устройства и прямого метода устройства в функции Azure.

  1. Создайте токен доступа в приложении IoT Central, см. Следующий фрагмент экрана:

  1. Добавьте этот токен доступа к настройкам приложения-функции. В этом примере используется имя параметра приложения AzureIoTCAccessToken. Обратите внимание, что этот токен доступа можно сохранить в хранилище ключей Azure, подробнее см. Здесь.

  2. Создайте функцию HttpTrigger в вашем приложении функций.

  3. Замените run.csx следующим кодом:

    #r "Newtonsoft.Json"
    #r "Microsoft.Azure.WebJobs.Extensions.Http"
    
    using System.Net;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Primitives;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using System.Linq;
    using System.Text;
    
    // reusable client proxy
    static HttpClientHelper iothub = new HttpClientHelper(Environment.GetEnvironmentVariable("AzureIoTCAccessToken"));
    
    public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");
    
        var atype = new { device = new { deviceId = "", properties = new JObject(), measurements = new JObject() } };
        var iotcobj = JsonConvert.DeserializeAnonymousType(await req.ReadAsStringAsync(), atype);
    
        // get deviceId, for test puspose use the device1
        string deviceId = iotcobj?.device?.deviceId ?? "device1";
    
        // get a device twins
        var response = await iothub.Client.GetAsync($"/twins/{deviceId}?api-version=2018-06-30");
        string jsontext = await response.Content.ReadAsStringAsync();
        log.LogInformation($"DeviceTwin: {JsonConvert.DeserializeObject(jsontext)}");
    
       // patch on desired property
       var patch = JsonConvert.SerializeObject(new { properties = new { desired = new { ping = DateTime.UtcNow } } });
       response = await iothub.Client.PatchAsync($"/twins/{deviceId}?api-version=2018-06-30", new StringContent(patch, Encoding.UTF8, "application/json"));
       jsontext = await response.Content.ReadAsStringAsync();
       log.LogInformation($"Patch: {JsonConvert.DeserializeObject(jsontext)}");
    
       // invoke a device method
       var method = new { methodName = "writeLine", timeoutInSeconds = 30, payload = new {input1 = 12345, input2 = "HelloDevice" } };
       response = await iothub.Client.PostAsJsonAsync($"/twins/{deviceId}/methods?api-version=2018-06-30", method );
       jsontext = await response.Content.ReadAsStringAsync();
       log.LogInformation($"DirectMethod: {JsonConvert.DeserializeObject(jsontext)}");
    
       return new OkObjectResult(jsontext);      
    }
    
    class HttpClientHelper
    {
        HttpClient client;
        string accessToken;
        dynamic iothub;
        long toleranceInSeconds = 60;
    
        public HttpClientHelper(string accessToken)
        {
            this.accessToken = accessToken;
            this.iothub = GetIoTHubTenant(accessToken);
            string hostname = GetHostNameFromSaSToken(this.iothub.iothubTenantSasToken.sasToken);
            client = new HttpClient() { BaseAddress = new Uri($"https://{hostname}") };
            client.DefaultRequestHeaders.Add("Authorization", iothub.iothubTenantSasToken.sasToken);
        }
        public HttpClient Client
        {
            get
            {
                if((new DateTime(1970, 1, 1)).AddSeconds(this.iothub.expiry - toleranceInSeconds) < DateTime.UtcNow)
                    SetAuthorizationHeader();
                return client;
            }
        }
        private void SetAuthorizationHeader()
        {
            lock (client)
            {
                if ((new DateTime(1970, 1, 1)).AddSeconds(this.iothub.expiry - toleranceInSeconds) < DateTime.UtcNow)
                {
                    if (client.DefaultRequestHeaders.Contains("Authorization"))
                        client.DefaultRequestHeaders.Remove("Authorization");
                    this.iothub = GetIoTHubTenant(this.accessToken);
                    client.DefaultRequestHeaders.Add("Authorization", this.iothub.iothubTenantSasToken.sasToken);
                }
            }
        }
        private string GetHostNameFromSaSToken(string sastoken)
        {
            var parts = sastoken.Replace("SharedAccessSignature", "").Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Split(new[] { '=' }, 2)).ToDictionary(x => x[0].Trim(), x => x[1].Trim());
            return parts["sr"] ?? "";
        }
    
        private dynamic GetIoTHubTenant(string iotcAccessToken)
        {
            string appId = GetHostNameFromSaSToken(iotcAccessToken);
            using (var hc = new HttpClient())
            {
                hc.DefaultRequestHeaders.Add("Authorization", accessToken);
                string address = $"https://api.azureiotcentral.com/v1-beta/applications/{appId}/diagnostics/sasTokens";
                var response = hc.PostAsync(address, new StringContent("{}", Encoding.UTF8, "application/json")).Result;
                return JsonConvert.DeserializeAnonymousType(response.Content.ReadAsStringAsync().Result, new { iothubTenantSasToken = new { sasToken = "" }, expiry = 0L });
            }
        }
    }
    

Примечание. Вышеприведенная реализация основана на сгенерированном токене доступа вашего приложения IoT Central, который недавно был выпущен для всеобщей доступности, см. Здесь. В случае изменения формата и т. Д. Все клиенты, тестировщики и т. Д., Включенные в вышеупомянутое решение, будут затронуты.

Для вашего конкретного случая использования единственный способ сделать это сегодня - это запустить рабочий процесс приложения логики с использованием его конечной точки HTTP из функций Azure. В приложении "Логика" вы можете создать рабочий процесс, используя центральный соединитель IoT Azure, который обновляет свойства и параметры устройства.

Мы работаем над API в IoT Central, которые могут освещать варианты использования, подобные вашему, так что следите за обновлениями!

Вы можете попробовать использовать Настройки, есть тип настройки, называемый "Переключить". Чтобы реализовать это, вы можете зайти в центральное приложение IoT с портала Azure. Затем:

  • Перейти на вкладку "Обозреватель устройств"

  • Выберите устройство

  • Нажмите на вкладку "Настройки" для устройства
  • Нажмите на кнопку "Изменить шаблон", расположенную в верхнем правом углу.
  • В разделе "Библиотека" найдите и нажмите "Переключить"

  • Введите настройки для функции переключения

Если вы хотите сделать это в масштабе, вы можете создать и запустить работу

В IoT Central вы можете управлять подключенными устройствами в масштабе, используя задания. Функциональность заданий позволяет выполнять массовые обновления свойств устройства, настроек и команд.

Другие вопросы по тегам