Пользовательское выделение устройств - установка начального Device Twin в функции Azure - PullRequest
0 голосов
/ 26 апреля 2019

Пользовательское распределение поддерживает настройку исходного устройства-близнеца, а также концентратора IoT. Двойник устройства не устанавливается.

Я настроил службу обеспечения устройств в Azure для использования пользовательской функции Azure. В функции Azure через пользовательский API мы запускаем логику, чтобы определить наилучшее расположение IoT-концентратора для устройства. В дополнение к назначению IoT Hub код предоставляет исходные данные об устройстве-близнецах, но он не работает.

Я следую примеру кода, описанному в этом блоге: https://sandervandevelde.wordpress.com/2018/12/29/custom-iot-hub-assignment-in-device-provisioning-service/

Я просмотрел несколько связанных с этим проблем с пользовательским размещением, но не нашел никого, кто использовал подход с пользовательской функцией Azure, как описано выше.

Ниже приведен фрагмент соответствующего кода из статьи блога выше.

var response = new Response(savefileresponse.AssignedHub);
//loading an instance of the initiTwin didn't work, try typing device twin values in manually
//response.initialTwin = savefileresponse.initialTwin;
response.initialTwin.properties.desired = new JObject();
response.initialTwin.properties.desired.PropOne = "2345";
response.initialTwin.properties.desired.PropTwo = "6789";

Ниже приведены определения классов, взятые из статьи блога. Обратите внимание на использование динамического типа для желаемых свойств. Кто-нибудь может подтвердить, что это правильный тип ответа на сообщение DPS?

public class AssignDeviceResponse
{
    public AssignDeviceResponse()
    {
        this.initialTwin = new ResponseTwin();
    }

    public ProvisioningRegistrationStatusType Status { get; set; }
    public string DeviceId { get; set; }
    public string AssignedHub { get; set; }
    public ResponseTwin initialTwin { get; set; }
}

#endregion

#region Microsoft DPS response contracts
public class Response
{
    public Response(string hostName)
    {
        iotHubHostName = hostName;
        initialTwin = new ResponseTwin();
    }

    public string iotHubHostName { get; set; }
    public ResponseTwin initialTwin { get; set; }
}

public class ResponseTwin
{
    public ResponseTwin()
    {
        properties = new ResponseProperties();
    }

    public dynamic tags { get; set; }
    public ResponseProperties properties { get; set; } // contains desired properties
}

public class ResponseProperties
{
    public dynamic desired { get; set; }
}
#endregion

После инициализации значение IoT Hub возвращается на устройство корректно. Затем я зашел в лазурный портал IoT Hub и показал двойное значение устройства. Ни одно из добавленных мной пользовательских свойств не отображается. Показанный ниже близнец, по-видимому, является некоторым IoT Hub по умолчанию, поскольку он также не соответствует двойнику в службе DPS.

{
"deviceId": "cde5d316-9c01-3961-b850-8f5c17cea937",
"etag": "AAAAAAAAAAE=",
"deviceEtag": "NzA1OTc5MzE1",
"status": "enabled",
"statusUpdateTime": "0001-01-01T00:00:00",
"connectionState": "Disconnected",
"lastActivityTime": "2019-04-26T16:41:11.6618195",
"cloudToDeviceMessageCount": 0,
"authenticationType": "selfSigned",
"x509Thumbprint": {
"primaryThumbprint": 
  "xxx",
"secondaryThumbprint": 
  "xxx"
},
"version": 2,
"properties": {
  "desired": {
    "$metadata": {
      "$lastUpdated": "2019-04-26T16:41:09.4381992Z"
   },
   "$version": 1
},
"reported": {
  "$metadata": {
    "$lastUpdated": "2019-04-26T16:41:09.4381992Z"
  },
  "$version": 1
 }
},
"capabilities": {
"iotEdge": false
}
}

Как установить двойное значение по умолчанию для устройства с помощью пользовательского выделения?

РЕДАКТИРОВАТЬ: Попробовав другой тип ответа на мою функцию, я решил также опубликовать код, который работает для меня, чтобы прочитать параметры, а также сформировать ответ, который действительно сериализуется через DPS. По-прежнему остается вопрос, как установить желаемые значения initialTwin. Вот код лазурной функции, который сериализуется обратно в DPS.

public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
                                                      HttpRequestMessage req, TraceWriter log)
    {
        string requestBody = await req.Content.ReadAsStringAsync();
        dynamic data = JsonConvert.DeserializeObject(requestBody);

        //Read out key information
        string deviceId = data.deviceRuntimeContext.registrationId;
        string certificate = data.deviceRuntimeContext.x509.clientCertificate;
        var response = new Response(data.linkedHubs?[0]);

        //Can't get initialTwin data back to DPS
        //response.initialTwin = new ResponseTwin() { }

        return req.CreateResponse<Response>(HttpStatusCode.OK, response);
    }

Ответы [ 4 ]

0 голосов
/ 29 мая 2019

Хорошо, после проработки этого с помощью Microsoft, вот ответ на вопрос.

1.) Реализация функции Azure в экземпляре V2 функций Azure

2.) Добавить ссылку на Microsoft.Azure.Devices.Shared

Код DPS ожидает экземпляр TwinState, как показано ниже

public class ResponseObj
{
    public string iotHubHostName { get; set; }
    public TwinState initialTwin { get; set; }
}

Затем сериализация обрабатывается этим типом возврата

return (ActionResult)new OkObjectResult(response);

Класс TwinState в Java: https://github.com/Azure/azure-iot-sdk-java/blob/a9c1487bede6463a6d67aadd68588cdaf92fd905/deps/src/main/java/com/microsoft/azure/sdk/iot/deps/twin/TwinState.java#L123

0 голосов
/ 29 апреля 2019

Из этого утверждения «Ни одно из пользовательских свойств, которые я добавил, не отображается» в вашем вопросе, я предполагаю, что устройство уже подготовлено, и вы настраивали устройство снова.В этом случае DPS предполагает, что решение клиента уже имеет подготовленное состояние, мы не хотим его перезаписывать.В зависимости от сценария вы можете предпринять действия, чтобы удовлетворить ваши потребности.Если это тестирование, и вы не беспокоитесь о ранее существующих данных, связанных с этим устройством, вы можете удалить устройство из концентратора и выполнить повторную подготовку.Теперь новые данные-близнецы будут отображаться в DPS.

0 голосов
/ 17 мая 2019

Я подозреваю, что это поможет кому-то еще, код ниже работает, но едва. Я не смог изменить динамический результат, не получив ошибку сериализации, но по крайней мере этот код функции Azure (не скрипт) работает. Ключ - это приведение в ответ.

   public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
                                                      HttpRequestMessage req, TraceWriter log)
    {
        log.Info("C# HTTP trigger function processed a request.");
        //log.LogInformation($"\nHeaders:\n\t{string.Join("\n\t", req.Headers.Select(i => $"{i.Key}={i.Value.First()}"))}");

        string requestBody = await req.Content.ReadAsStringAsync();
        dynamic data = JsonConvert.DeserializeObject(requestBody);
        string iotHub = data.linkedHubs[0];

        dynamic result = new
        {
            iotHubHostName = $"{iotHub}",
            initialTwin = new
            {
                tags = new { abcd = 12345 },
                properties = new
                {
                    desired = new
                    {
                        PropOne = "2345",
                        PropTwo = "6789"
                    }
                }
            }
        };
        log.Info($"Sending back result: {Convert.ToString(result)}");

        return req.CreateResponse<dynamic>(HttpStatusCode.OK, (Object)result);
    }
0 голосов
/ 27 апреля 2019

следующий фрагмент кода является примером пользовательской функции обход в индивидуальной регистрации:

#r "Newtonsoft.Json"

using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");
    //log.LogInformation($"\nHeaders:\n\t{string.Join("\n\t", req.Headers.Select(i => $"{i.Key}={i.Value.First()}"))}");

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    string iotHub = data?.individualEnrollment?.iotHubs?[0];

    dynamic result = new { iotHubHostName = $"{iotHub}" };
    return (ActionResult)new OkObjectResult(result);
}

В случае инициализации двойника устройства нам нужно добавить объект свойства initialTwin , как показано в следующем примере:

dynamic result = new { 
    iotHubHostName = $"{iotHub}", 
    initialTwin = new { 
        tags = new { abcd = 12345}, 
        properties = new { 
            desired = new { 
                PropOne = "2345",
                PropTwo = "6789"
                }
            }
        }
    };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...