/// <summary> /// This method is called whenever the module is sent a message from the EdgeHub. /// It just pipe the messages without any change. /// It prints all the incoming messages. /// </summary> static async Task <MessageResponse> PipeMessage(Message message, object userContext) { var userContextValues = userContext as Tuple <ModuleClient, GatewayController>; if (userContextValues == null) { throw new InvalidOperationException("UserContext doesn't contain expected values"); } ModuleClient ioTHubModuleClient = userContextValues.Item1; GatewayController gatewayHandle = userContextValues.Item2; if (gatewayHandle.GatewayConfig == null) { Console.WriteLine("Module configuration is empty. Message processing terminated"); return(MessageResponse.Abandoned); } else if (gatewayHandle.GatewayConfig.ReportedTelemetry == null) { Console.WriteLine("No telemetry signals configured for remote monitoring. Message processing terminated"); return(MessageResponse.Abandoned); } int counterValue = Interlocked.Increment(ref counter); byte[] messageBytes = message.GetBytes(); string messageString = Encoding.UTF8.GetString(messageBytes); if (!string.IsNullOrEmpty(messageString)) { Console.WriteLine($"Parsing message: {counterValue}, Body: [{messageString}]"); List <SignalTelemetry> telemetryData = JsonConvert.DeserializeObject <List <SignalTelemetry> >(messageString); if (telemetryData.Count > 0) { await gatewayHandle.ProcessAbbDriveProfileTelemetry(telemetryData); } } else { throw new InvalidOperationException("Error: message body is empty"); } return(MessageResponse.Completed); }
/// <summary> /// Initializes the ModuleClient and sets up the callback to receive /// messages containing temperature information /// </summary> static async Task Init() { MqttTransportSettings mqttSetting = new MqttTransportSettings(TransportType.Mqtt_Tcp_Only); ITransportSettings[] settings = { mqttSetting }; // Open a connection to the Edge runtime ModuleClient ioTHubModuleClient = await ModuleClient.CreateFromEnvironmentAsync(settings); await ioTHubModuleClient.OpenAsync(); Console.WriteLine("IoT Hub module client initialized."); // Read Module Twin Desired Properties Console.WriteLine("Reading module Twin from IoT Hub."); var moduleTwin = await ioTHubModuleClient.GetTwinAsync(); CancellationTokenSource cts = new CancellationTokenSource(); // Read Module Twin Desired Properties Console.WriteLine("Starting Gateway controller handler process."); GatewayController controller = await GatewayController.Start(ioTHubModuleClient, moduleTwin, cts.Token); var userContext = new Tuple <ModuleClient, GatewayController>(ioTHubModuleClient, controller); // Register callback to be called when a message is received by the module Console.WriteLine(String.Format("Registreing call back for input named {0}.", InputName)); await ioTHubModuleClient.SetInputMessageHandlerAsync(InputName, PipeMessage, userContext); // Attach callback for Twin desired properties updates await ioTHubModuleClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertiesUpdate, userContext); Console.WriteLine("Setting up cancelation for controler handler process."); AssemblyLoadContext.Default.Unloading += (ctx) => cts.Cancel(); Console.CancelKeyPress += (sender, cpe) => cts.Cancel(); Console.WriteLine("Gateway controller handler Initialization sucessfull."); }
/// <summary> /// Callback to handle Twin desired properties updates� /// </summary> static async Task OnDesiredPropertiesUpdate(TwinCollection desiredProperties, object userContext) { var userContextValues = userContext as Tuple <ModuleClient, GatewayController>; if (userContextValues == null) { throw new InvalidOperationException("UserContext doesn't contain expected values"); } ModuleClient ioTHubModuleClient = userContextValues.Item1; GatewayController gatewayHandle = userContextValues.Item2; try { // stop all activities while updating configuration await ioTHubModuleClient.SetInputMessageHandlerAsync(InputName, DummyCallBack, null); GatewayModel updateModel = GatewayController.CreateGatewayModel(desiredProperties); gatewayHandle.UpdateGatewayModel(updateModel); // restore message handling await ioTHubModuleClient.SetInputMessageHandlerAsync(InputName, PipeMessage, userContext); } catch (AggregateException ex) { foreach (Exception exception in ex.InnerExceptions) { Console.WriteLine(); Console.WriteLine("Error when receiving desired property: {0}", exception); } } catch (Exception ex) { Console.WriteLine(); Console.WriteLine("Error when receiving desired property: {0}", ex.Message); } }
/** * Initialize and Send DeviceInfo message */ public static async Task <GatewayController> Start(ModuleClient ioTHubModuleClient, Twin moduleTwin, CancellationToken cancelToken) { if (moduleTwin == null || moduleTwin.Properties == null) { throw new ArgumentOutOfRangeException("No module Twin desired properties provided."); } GatewayModel gatewayDeviceConfig = CreateGatewayModel(moduleTwin.Properties.Desired); GatewayController gatewayHandle = new GatewayController(gatewayDeviceConfig); DeviceProperties gatewayProperties = gatewayHandle.GatewayDeviceConfig.DeviceProperties; gatewayProperties.DeviceID = moduleTwin.ModuleId; // This is the place you can specify the metadata for your device. The below fields are not mandatory. gatewayProperties.UpdatedTime = DateTime.UtcNow.ToString(); gatewayProperties.FirmwareVersion = "1.0"; gatewayProperties.InstalledRAM = "Unknown"; gatewayProperties.Manufacturer = "Unknown"; gatewayProperties.ModelNumber = "Unknown"; gatewayProperties.Platform = RuntimeInformation.OSDescription; gatewayProperties.Processor = Enum.GetName(typeof(Architecture), RuntimeInformation.OSArchitecture); gatewayProperties.SerialNumber = "Unknown"; // Create send task await Task.Factory.StartNew(async() => { while (true) { if (gatewayHandle.GatewayConfig.ReportEnabledState) { bool hasMutex = false; try{ hasMutex = gatewayHandle.telemetryMutex.WaitOne(gatewayHandle.GatewayConfig.ReportingInterval); if (hasMutex) { if (gatewayHandle.Telemetry.Count > 0) // Send current telemetry data { gatewayHandle.SendData(ioTHubModuleClient, gatewayHandle.Telemetry); gatewayHandle.Telemetry.Clear(); } if (gatewayHandle.IsDeviceInfoUpdated) // Send DeviceInfo structure into module twin { string serializedStr = JsonConvert.SerializeObject(gatewayHandle.GatewayDeviceConfig); TwinCollection reported = JsonConvert.DeserializeObject <TwinCollection>(serializedStr); await ioTHubModuleClient.UpdateReportedPropertiesAsync(reported); gatewayHandle.IsDeviceInfoUpdated = false; } } else { Console.WriteLine("Error. Can't get mutext for telemetry data for {0} ms. Timeout!", gatewayHandle.GatewayConfig.ReportingInterval); } }catch (Exception ex) { Console.WriteLine("Error upload data: {0}, {1}", ex.Message, ex.StackTrace); } finally{ if (hasMutex) { gatewayHandle.telemetryMutex.ReleaseMutex(); } } } await Task.Delay(gatewayHandle.GatewayConfig.ReportingInterval); if (cancelToken.IsCancellationRequested) { // Cancel was called Console.WriteLine("Sending task canceled"); break; } } }, cancelToken); return(gatewayHandle); }