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