Azure functions 设备配置自定义分配-在azure函数中设置初始设备

Azure functions 设备配置自定义分配-在azure函数中设置初始设备,azure-functions,azure-iot-hub,Azure Functions,Azure Iot Hub,自定义分配支持设置初始设备双胞胎和物联网集线器。该设备未设置 我已将Azure中的设备配置服务配置为使用自定义Azure功能。在Azure函数中,通过自定义API,我们运行逻辑来确定设备的最佳IoT集线器位置。除了物联网集线器分配外,该代码还提供初始设备双胞胎数据,但不起作用 下面是本博客中描述的代码示例: 我已经查看了几个相关的自定义分配问题,但没有发现任何人使用上述自定义azure函数方法 下面是上面博客文章中的相关代码片段 var response = new Response(save

自定义分配支持设置初始设备双胞胎和物联网集线器。该设备未设置

我已将Azure中的设备配置服务配置为使用自定义Azure功能。在Azure函数中,通过自定义API,我们运行逻辑来确定设备的最佳IoT集线器位置。除了物联网集线器分配外,该代码还提供初始设备双胞胎数据,但不起作用

下面是本博客中描述的代码示例:

我已经查看了几个相关的自定义分配问题,但没有发现任何人使用上述自定义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集线器值将正确返回到设备。然后我进入azure门户,IoT中心,展示设备的双重价值。我添加的自定义属性均未显示。下面的孪生兄弟显然是一些物联网枢纽默认,因为它与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的azure函数代码

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);
    }
公共静态异步任务运行([HttpTrigger(AuthorizationLevel.Function,“get”,“post”,Route=null)]
HttpRequestMessage请求,TraceWriter日志)
{
string requestBody=wait req.Content.ReadAsStringAsync();
动态数据=JsonConvert.DeserializeObject(requestBody);
//读出关键信息
字符串deviceId=data.deviceRuntimeContext.registrationId;
字符串证书=data.deviceRuntimeContext.x509.clientCertificate;
var响应=新响应(data.linkedHubs?[0]);
//无法将initialTwin数据恢复到DPS
//response.initialTwin=新ResponseTwin(){}
返回请求CreateResponse(HttpStatusCode.OK,response);
}

以下代码片段是单个注册中的绕过自定义函数的示例:

#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);
}

从您的问题中的“没有显示我添加的自定义属性”这句话中,我假设该设备已设置,并且您正在再次设置该设备。在这种情况下,DPS假定客户的解决方案已经具有已设置状态,我们不希望覆盖它。根据具体情况,您可以采取措施来满足您的需求。如果这是测试,而您不关心与此设备相关的先前存在的数据,则可以从集线器中删除该设备并重新配置。现在,DPS将显示新的双胞胎数据

我怀疑这会对其他人有所帮助,下面的代码可以工作,但几乎没有。我无法修改动态结果而不出现序列化错误,但至少这个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);
    }
公共静态异步任务运行([HttpTrigger(AuthorizationLevel.Function,“get”,“post”,Route=null)]
HttpRequestMessage请求,TraceWriter日志)
{
Info(“C#HTTP触发器函数处理了一个请求。”);
//log.LogInformation($“\n标题:\n\t{string.Join(“\n\t”,req.Headers.Select(i=>$”{i.Key}={i.Value.First())});
string requestBody=wait req.Content.ReadAsStringAsync();
动态数据=JsonConvert.DeserializeObject(requestBody);
字符串iotHub=data.linkedhub[0];
动态结果=新
{
iotHubHostName=$“{iotHub}”,
initialTwin=新
{
tags=new{abcd=12345},
属性=新
{
期望的=新的
{
PropOne=“2345”,
PropTwo=“6789”
}
}
}
};
log.Info($“发送回结果:{Convert.ToString(result)}”);
返回请求CreateResponse(HttpStatusCode.OK,(对象)结果);
}

好的,在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);
Java中的TwinState类:

我的场景是一个新的设备配置过程。我尝试将您的“结果”放入代码中。当我这样做时,DPS调用者收到一个失败,原因是:“未能反序列化来自自定义分配webhook的响应。”您不需要创建强类型,只需在AF正文中替换它即可。注意,旁路和initialTwin属性等动态结果均已成功测试。
return (ActionResult)new OkObjectResult(response);