public static async Task<KustoOperations> GetClientAsync() { await semaphoreSlim.WaitAsync(); try { return instance ?? (instance = CreateInstance()); } finally { semaphoreSlim.Release(); } }
public async Task SaveDeviceTwinOperationAsync(string eventData, ILogger log, string tenant, string deviceId, string operationType, TelemetryTimestamp timeStamp, EventHubHelper eventHubHelper) { try { string deviceTwin = eventData; Twin twin = null; JObject deviceTwinJson = new JObject(); deviceTwinJson.Add(DeviceTelemetryKeyConstants.DeviceId, deviceId.ToString()); deviceTwinJson.Add(DeviceTelemetryKeyConstants.TimeStamp, timeStamp.DateTime); deviceTwinJson.Add(DeviceTelemetryKeyConstants.TimeReceived, timeStamp.EpochTimestamp); deviceTwinJson.Add(DeviceTelemetryKeyConstants.EventOpType, operationType); deviceTwinJson.Add(DeviceTelemetryKeyConstants.IsDeleted, false); if (operationType.ToString().Equals("createDeviceIdentity")) { deviceTwinJson.Add(DeviceTelemetryKeyConstants.DeviceCreatedDate, timeStamp.DateTime); try { twin = await TenantConnectionHelper.GetRegistry(Convert.ToString(tenant)).GetTwinAsync(deviceId.ToString()); deviceTwin = twin.ToJson(); } catch (Exception e) { log.LogError($"Unable to fetch DeviceId: {deviceId} device twin from iothub of tenant: {tenant}.", e); } } else { JObject previousTwin = null; KustoOperations kustoClient = await KustoOperations.GetClientAsync(); string kustoQuery = $"DeviceTwin | where DeviceId == \"{deviceId}\" | summarize arg_max(TimeStamp, *) by DeviceId | where IsDeleted == false"; var deviceTwinList = await kustoClient.QueryAsync <DeviceTwinModel>($"IoT-{tenant}", kustoQuery, null); DeviceTwinModel preDeviceTwin = deviceTwinList.FirstOrDefault(); if (preDeviceTwin != null) { previousTwin = preDeviceTwin.Twin; deviceTwinJson.Add(DeviceTelemetryKeyConstants.DeviceCreatedDate, preDeviceTwin.DeviceCreatedDate); } else { deviceTwinJson.Add(DeviceTelemetryKeyConstants.DeviceCreatedDate, default(DateTime)); // Set Device Created Date to Default if twin is not present in storage. try { twin = await TenantConnectionHelper.GetRegistry(Convert.ToString(tenant)).GetTwinAsync(deviceId.ToString()); if (twin != null) { previousTwin = JObject.Parse(twin.ToJson()); } } catch (Exception e) { log.LogError($"Unable to fetch DeviceId: {deviceId} device twin from iothub of tenant: {tenant}.", e); } } switch (operationType) { case "deviceConnected": if (preDeviceTwin != null) { previousTwin["connectionState"] = "Connected"; previousTwin["lastActivityTime"] = timeStamp.DateTime; } break; case "deviceDisconnected": if (preDeviceTwin != null) { previousTwin["connectionState"] = "Disconnected"; previousTwin["lastActivityTime"] = timeStamp.DateTime; } break; case "updateTwin": if (preDeviceTwin != null) { JObject twinFragment = JObject.Parse(eventData); previousTwin = previousTwin.UpdateJson(twinFragment); } else { previousTwin = JObject.Parse(eventData); } break; case "deleteDeviceIdentity": deviceTwinJson[DeviceTelemetryKeyConstants.IsDeleted] = true; break; default: break; } deviceTwin = previousTwin?.ToString(); } deviceTwinJson.Add(DeviceTelemetryKeyConstants.Data, deviceTwin); // Save the Device Twin Data to EventHub for further processing var byteMessage = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(deviceTwinJson)); var eventDeviceTwinData = new Azure.Messaging.EventHubs.EventData(byteMessage); eventDeviceTwinData.Properties.Add("deviceid", deviceId.ToString()); await eventHubHelper.SendMessageToEventHub($"{tenant}-devicetwin", new Azure.Messaging.EventHubs.EventData[] { eventDeviceTwinData }); } catch (Exception exception) { throw new ApplicationException($"Save Device Twin operation failed: {exception}, operation type: {operationType}, tenant: {tenant}, deviceId {deviceId}"); } }