static async Task DeviceTelemetrySend(DeviceClient deviceClient, PayloadUplink payloadObject) { JObject telemetryEvent = new JObject { { "DeviceEUI", payloadObject.DeviceEui }, { "Retry", payloadObject.IsRetry }, { "Counter", payloadObject.Counter }, { "DeviceID", payloadObject.DeviceId }, { "ApplicationID", payloadObject.ApplicationId }, { "Port", payloadObject.Port }, { "PayloadRaw", payloadObject.PayloadRaw }, { "ReceivedAtUTC", payloadObject.Metadata.ReceivedAtUtc } }; // If the payload has been unpacked in TTN backend add fields to telemetry event payload if (payloadObject.PayloadFields != null) { EnumerateChildren(telemetryEvent, payloadObject.PayloadFields); } // Send the message to Azure IoT Hub/Azure IoT Central using (Message ioTHubmessage = new Message(Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(telemetryEvent)))) { // Ensure the displayed time is the acquired time rather than the uploaded time. esp. important for when messages that ended up // in poison queue are returned to the processing queue. ioTHubmessage.Properties.Add("iothub-creation-time-utc", payloadObject.Metadata.ReceivedAtUtc.ToString("s", CultureInfo.InvariantCulture)); await deviceClient.SendEventAsync(ioTHubmessage); } }
public static async Task UplinkRun( [QueueTrigger("%UplinkQueueName%", Connection = "AzureStorageConnectionString")] PayloadUplink payload, ILogger log) { // Quick n dirty hack to see what difference (if any) not processing retries makes if (payload.IsRetry) { log.LogInformation("DevID:{DeviceId} Counter:{Counter} AppID:{ApplicationId} Uplink message retry", payload.DeviceId, payload.Counter, payload.ApplicationId); return; } log.LogInformation("DevID:{DeviceId} Counter:{Counter} AppID:{ApplicationId} Uplink message device processing start", payload.DeviceId, payload.Counter, payload.ApplicationId); ApplicationConfiguration.Initialise(); string registrationId = ApplicationConfiguration.RegistrationIdResolve(payload.ApplicationId, payload.Port, payload.DeviceId); CacheItemPolicy cacheItemPolicy = new CacheItemPolicy() { SlidingExpiration = new TimeSpan(1, 0, 0, 0), //RemovedCallback }; DeviceContext deviceContext = new DeviceContext() { Uplink = null, Downlink = new Uri(payload.DownlinkUrl) }; // See if the device has already been provisioned or is being provisioned on another thread. if (DeviceClients.Add(registrationId, deviceContext, cacheItemPolicy)) { log.LogInformation("RegID:{registrationId} Device provisioning start", registrationId); try { // Get DeviceClient if first time device seen deviceContext.Uplink = await DeviceRegistration(payload.ApplicationId, payload.DeviceId, payload.Port); } catch (Exception ex) { if (DeviceClients.Remove(registrationId) == null) { log.LogWarning("RegID:{registrationID} Device Registration TryRemove failed", registrationId); } log.LogError(ex, "RegID:{registrationID} Device Registration failed", registrationId); throw; } DeviceClients.Set(registrationId, deviceContext, cacheItemPolicy); log.LogInformation("RegID:{registrationId} Assigned to IoTHub", registrationId); } // Wait for the Device Provisioning Service to complete on this or other thread log.LogInformation("RegID:{registrationId} Device provisioning polling start", payload.DeviceId); int deviceProvisioningPollingDelay = ApplicationConfiguration.DpsDeviceProvisioningPollingDelay(); // Wait for the deviceClient to be configured if process kicked off on another thread, no timeout as will get taken care of by function timeout... do { deviceContext = (DeviceContext)DeviceClients.Get(registrationId); if (deviceContext == null) { log.LogError("RegID:{registrationId} DeviceContext provisioning polling Get failed", registrationId); throw new ApplicationException($"RegID:{registrationId} DeviceContext provisioning polling Get failed"); } if (deviceContext.Uplink == null) { log.LogInformation($"RegID:{registrationId} Device provisioning polling delay:{deviceProvisioningPollingDelay}mSec", registrationId, deviceProvisioningPollingDelay); await Task.Delay(deviceProvisioningPollingDelay); } }while (deviceContext.Uplink == null); log.LogInformation("DevID:{DeviceId} Counter:{counter} Payload Send start", payload.DeviceId, payload.Counter); try { await DeviceTelemetrySend(deviceContext.Uplink, payload); } catch (Exception ex) { if (DeviceClients.Remove(registrationId) == null) { log.LogWarning("DevID:{DeviceId} Counter:{Counter} Payload SendEventAsync TryRemove failed", payload.DeviceId, payload.Counter); } log.LogError(ex, "DevID:{DeviceId} Counter:{Counter} Telemetry event send failed", payload.DeviceId, payload.Counter); throw; } log.LogInformation("DevID:{DeviceId} Counter:{Counter} Uplink message device processing completed", payload.DeviceId, payload.Counter); }