public void TwinState_SucceedOnFromJson()
        {
            // arrange
            TwinCollection tags = SampleTags;
            TwinCollection desiredProperties = SampleDesiredProperties;

            // act
            TwinState initialTwin = JsonConvert.DeserializeObject <TwinState>(FullInitialTwinJSON);

            // assert
            TestAssert.AreEqualJson(FullInitialTwinJSON, JsonConvert.SerializeObject(initialTwin));
        }
        public void TwinState_SucceedOnTagsWitoutDesiredProperties()
        {
            // arrange
            TwinCollection tags = SampleTags;
            TwinCollection desiredProperties = null;

            // act
            TwinState initialTwin = new TwinState(tags, desiredProperties);

            // assert
            Assert.AreEqual(tags, initialTwin.Tags);
            Assert.IsNull(initialTwin.DesiredProperties);
        }
        public void TwinState_SucceedOnNull()
        {
            // arrange
            TwinCollection tags = null;
            TwinCollection desiredProperties = null;

            // act
            TwinState initialTwin = new TwinState(tags, desiredProperties);

            // assert
            Assert.IsNull(initialTwin.Tags);
            Assert.IsNull(initialTwin.DesiredProperties);
        }
        public void TwinState_SucceedOnToJson()
        {
            // arrange
            TwinCollection tags = SampleTags;
            TwinCollection desiredProperties = SampleDesiredProperties;
            TwinState      initialTwin       = new TwinState(tags, desiredProperties);

            // act
            string jsonResult = JsonConvert.SerializeObject(initialTwin);

            // assert
            TestAssert.AreEqualJson(FullInitialTwinJSON, jsonResult);
        }
        public void TwinState_SucceedOnDesiredPropertiesAndTags()
        {
            // arrange
            TwinCollection tags = SampleTags;
            TwinCollection desiredProperties = SampleDesiredProperties;

            // act
            TwinState initialTwin = new TwinState(tags, desiredProperties);

            // assert
            Assert.AreEqual(tags, initialTwin.Tags);
            Assert.AreEqual(desiredProperties, initialTwin.DesiredProperties);
        }
        public void TwinStateSucceedOnDesiredPropertiesWitoutTags()
        {
            // arrange
            TwinCollection tags = null;
            TwinCollection desiredProperties = SampleDesiredProperties;

            // act
            var initialTwin = new TwinState(tags, desiredProperties);

            // assert
            Assert.IsNull(initialTwin.Tags);
            Assert.AreEqual(desiredProperties, initialTwin.DesiredProperties);
        }
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
        {
            // Get request body
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();

            log.LogDebug($"Request.Body: {requestBody}");
            dynamic data = JsonConvert.DeserializeObject(requestBody);

            // Get registration ID of the device
            string regId = data?.deviceRuntimeContext?.registrationId;

            bool        fail    = false;
            string      message = "Uncaught error";
            ResponseObj obj     = new ResponseObj();

            // Must have unique registration ID on DPS request
            if (regId == null)
            {
                message = "Registration ID not provided for the device.";
                log.LogInformation("Registration ID: NULL");
                fail = true;
            }
            else
            {
                string[] hubs = data?.linkedHubs.ToObject <string[]>();

                // Must have hubs selected on the enrollment
                if (hubs == null)
                {
                    message = "No hub group defined for the enrollment.";
                    log.LogInformation("linkedHubs: NULL");
                    fail = true;
                }
                else
                {
                    // Find or create twin based on the provided registration ID and model ID
                    dynamic payloadContext = data?.deviceRuntimeContext?.payload;
                    string  dtmi           = payloadContext.modelId;
                    log.LogDebug($"payload.modelId: {dtmi}");
                    string dtId = await FindOrCreateTwin(dtmi, regId, log);

                    // Get first linked hub (TODO: select one of the linked hubs based on policy)
                    obj.iotHubHostName = hubs[0];

                    // Specify the initial tags for the device.
                    TwinCollection tags = new TwinCollection();
                    tags["dtmi"] = dtmi;
                    tags["dtId"] = dtId;

                    // Specify the initial desired properties for the device.
                    TwinCollection properties = new TwinCollection();

                    // Add the initial twin state to the response.
                    TwinState twinState = new TwinState(tags, properties);
                    obj.initialTwin = twinState;
                }
            }

            log.LogDebug("Response: " + ((obj.iotHubHostName != null) ? JsonConvert.SerializeObject(obj) : message));

            return((fail)
                ? new BadRequestObjectResult(message)
                : (ActionResult) new OkObjectResult(obj));
        }
示例#8
0
        public static async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest request,
            ILogger log)
        {
            string      requestBody       = await new StreamReader(request.Body).ReadToEndAsync();
            string      errorMessage      = string.Empty;
            DpsResponse response          = new DpsResponse();
            bool        isGroupEnrollment = false;
            string      registrationId;
            DateTime    localDate = DateTime.Now;

            _logger = log;

            dynamic requestData = JsonConvert.DeserializeObject(requestBody);

            if (requestData.ContainsKey("enrollmentGroup"))
            {
                log.LogInformation("Group Enrollment");
                registrationId    = requestData?.enrollmentGroup?.enrollmentGroupId;
                isGroupEnrollment = true;
            }
            else
            {
                log.LogInformation("Individual Enrollment");
                registrationId = requestData?.deviceRuntimeContext?.registrationId;
            }

            string[] iothubs = requestData?.linkedHubs.ToObject <string[]>();

            log.LogInformation($"dps_processor : Request.Body: {JsonConvert.SerializeObject(requestData, Formatting.Indented)}");

            #region payload_sample

            /* Payload Example
             * {
             * "enrollmentGroup": {
             *  "enrollmentGroupId": "PVDemo-Group-Enrollment-Custom-Allocation",
             *  "attestation": {
             *    "type": "symmetricKey"
             *  },
             *  "capabilities": {
             *    "iotEdge": false
             *  },
             *  "etag": "\"1a055216-0000-0800-0000-60a637160000\"",
             *  "provisioningStatus": "enabled",
             *  "reprovisionPolicy": {
             *    "updateHubAssignment": true,
             *    "migrateDeviceData": true
             *  },
             *  "createdDateTimeUtc": "2021-05-20T10:15:51.2294536Z",
             *  "lastUpdatedDateTimeUtc": "2021-05-20T10:16:54.6543548Z",
             *  "allocationPolicy": "custom",
             *  "iotHubs": [
             *    "PVDemo-IoTHub.azure-devices.net"
             *  ],
             *  "customAllocationDefinition": {
             *    "webhookUrl": "https://pvdemo-functions.azurewebsites.net/api/dps_processor?****",
             *    "apiVersion": "2019-03-31"
             *  }
             * },
             * "deviceRuntimeContext": {
             *  "registrationId": "WioTerminal",
             *  "symmetricKey": {},
             *  "payload": {
             *    "modelId": "dtmi:seeedkk:wioterminal:wioterminal_aziot_example_gps;5"
             *  }
             * },
             * "linkedHubs": [
             *  "PVDemo-IoTHub.azure-devices.net"
             * ]
             * }
             */
            #endregion

            try
            {
                if (registrationId == null)
                {
                    log.LogError($"Missing Registration ID");
                }
                else if (iothubs == null)
                {
                    errorMessage = "No linked hubs for this enrollment.";
                    log.LogError("linked IoT Hub");
                }
                else
                {
                    // Example of specific tasks based on Enrollment
                    if (registrationId.Contains("Group"))
                    {
                        // do specifics based on registration id
                    }

                    if (isGroupEnrollment)
                    {
                        // do specifics for Group Enrollment
                    }
                    else
                    {
                        // do specifics for Individual Enrollment
                    }

                    foreach (var iothub in iothubs)
                    {
                        // do specifics for linked hubs
                        // e.g. pick up right IoT Hub based on device id
                        response.iotHubHostName = iothub;
                    }


                    // build tags for the device
                    // tags are for solution only, devices do not see tags
                    // https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-device-twins#device-twins
                    TwinCollection twinTags = new TwinCollection();
                    twinTags["TagFromDpsWebHook"] = "CustomAllocationSample";

                    // build initial twin (Desired Properties) for the device
                    // these values will be passed to the device during Initial Get
                    TwinCollection desiredProperties = new TwinCollection();
                    desiredProperties["FromDpsWebHook1"] = "InitialTwinByCustomAllocation";
                    desiredProperties["FromDpsWebHook2"] = registrationId;

                    // Get DTDL Model Id
                    string componentName = string.Empty;
                    IReadOnlyDictionary <Dtmi, DTEntityInfo> parsedModel = null;
                    string modelId = requestData?.deviceRuntimeContext?.payload?.modelId;

                    if (!string.IsNullOrEmpty(modelId))
                    {
                        // If DTMI is given to DPS payload, parse it.
                        parsedModel = await DeviceModelResolveAndParse(modelId);
                    }

                    if (parsedModel != null)
                    {
                        string propertyName = "Hostname";
                        // Example : Setting Writable Property using Device Model
                        // We are interested in properties
                        DTPropertyInfo property = parsedModel.Where(r => r.Value.EntityKind == DTEntityKind.Property).Select(x => x.Value as DTPropertyInfo).Where(x => x.Writable == true).Where(x => x.Name == propertyName).FirstOrDefault();

                        if (property != null)
                        {
                            var dateString = $"{localDate.Year}{localDate.Month}{localDate.Day}-{localDate.Hour}{localDate.Minute}{localDate.Second}";
                            log.LogInformation($"Found Writable Property '{propertyName}'");

                            // If no match, this interface must be from Component
                            if (!modelId.Equals(property.DefinedIn.AbsoluteUri))
                            {
                                var component = parsedModel.Where(r => r.Value.EntityKind == DTEntityKind.Component).Select(x => x.Value as DTComponentInfo).Where(x => x.Schema.Id.ToString() == property.ChildOf.AbsoluteUri).FirstOrDefault();
                                if (component != null)
                                {
                                    TwinCollection componentTwin         = new TwinCollection();
                                    TwinCollection hostnameComponentTwin = new TwinCollection();
                                    // Hostname takes a parameter as JSON Object
                                    // JSON looks like this
                                    // "desired" : {
                                    //   "R700": {
                                    //     "__t": "c",
                                    //     "Hostname" : {
                                    //       "hostname" : "<New Name>"
                                    //     }
                                    //   }
                                    // }
                                    if (property.Schema.EntityKind == DTEntityKind.Object)
                                    {
                                        DTObjectInfo parameterObj = property.Schema as DTObjectInfo;
                                        hostnameComponentTwin[parameterObj.Fields[0].Name] = $"impinj-{dateString}";
                                        componentTwin[property.Name]      = hostnameComponentTwin;
                                        componentTwin["__t"]              = "c";
                                        desiredProperties[component.Name] = componentTwin;
                                    }
                                }
                            }
                            else
                            {
                                desiredProperties[property.Name] = $"impinj-{dateString}";
                            }
                        }
                    }

                    TwinState twinState = new TwinState(twinTags, desiredProperties);

                    response.initialTwin = twinState;
                }
            }
            catch (Exception ex)
            {
                log.LogError($"Exception {ex}");
                errorMessage = ex.Message;
            }

            if (!string.IsNullOrEmpty(errorMessage))
            {
                log.LogError($"Error : {errorMessage}");
                return(new BadRequestObjectResult(errorMessage));
            }

            log.LogInformation($"Response to DPS \r\n {JsonConvert.SerializeObject(response)}");
            return((ActionResult) new OkObjectResult(response));
        }