/// <summary> /// Module behavior: /// Sends data periodically (with default frequency of 5 seconds). /// Data trend: /// - Machine Temperature regularly rises from 21C to 100C in regularly with jitter /// - Machine Pressure correlates with Temperature 1 to 10psi /// - Ambient temperature stable around 21C /// - Humidity is stable with tiny jitter around 25% /// Method for resetting the data stream /// </summary> static async Task SendEvents( ModuleClient moduleClient, TimeSpan messageDelay, bool sendForever, int messageCount, SimulatorParameters sim, CancellationTokenSource cts) { int count = 1; double currentTemp = sim.MachineTempMin; double normal = (sim.MachinePressureMax - sim.MachinePressureMin) / (sim.MachineTempMax - sim.MachineTempMin); while (!cts.Token.IsCancellationRequested && (sendForever || messageCount >= count)) { if (Reset) { currentTemp = sim.MachineTempMin; Reset.Set(false); } if (currentTemp > sim.MachineTempMax) { currentTemp += Rnd.NextDouble() - 0.5; // add value between [-0.5..0.5] } else { currentTemp += -0.25 + (Rnd.NextDouble() * 1.5); // add value between [-0.25..1.25] - average +0.5 } var tempData = new MessageBody { Machine = new Machine { Temperature = currentTemp, Pressure = sim.MachinePressureMin + ((currentTemp - sim.MachineTempMin) * normal), }, Ambient = new Ambient { Temperature = sim.AmbientTemp + Rnd.NextDouble() - 0.5, Humidity = Rnd.Next(24, 27) }, TimeCreated = DateTime.UtcNow }; string dataBuffer = JsonConvert.SerializeObject(tempData); var eventMessage = new Message(Encoding.UTF8.GetBytes(dataBuffer)); Console.WriteLine($"\t{DateTime.Now.ToLocalTime()}> Sending message: {count}, Body: [{dataBuffer}]"); await moduleClient.SendEventAsync("temperatureOutput", eventMessage); await Task.Delay(messageDelay, cts.Token); count++; } if (messageCount < count) { Console.WriteLine($"Done sending {messageCount} messages"); } }
static async Task <int> MainAsync() { Console.WriteLine($"[{DateTime.UtcNow.ToString("MM/dd/yyyy hh:mm:ss.fff tt", CultureInfo.InvariantCulture)}] Main()"); IConfiguration configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("config/appsettings.json", optional: true) .AddEnvironmentVariables() .Build(); TimeSpan messageDelay = configuration.GetValue("MessageDelay", TimeSpan.FromSeconds(5)); int messageCount = configuration.GetValue(MessageCountConfigKey, 500); bool sendForever = messageCount < 0; var sim = new SimulatorParameters { MachineTempMin = configuration.GetValue <double>("machineTempMin", 21), MachineTempMax = configuration.GetValue <double>("machineTempMax", 100), MachinePressureMin = configuration.GetValue <double>("machinePressureMin", 1), MachinePressureMax = configuration.GetValue <double>("machinePressureMax", 10), AmbientTemp = configuration.GetValue <double>("ambientTemp", 21), HumidityPercent = configuration.GetValue("ambientHumidity", 25) }; string messagesToSendString = sendForever ? "unlimited" : messageCount.ToString(); Console.WriteLine( $"Initializing simulated temperature sensor to send {messagesToSendString} messages, at an interval of {messageDelay.TotalSeconds} seconds.\n" + $"To change this, set the environment variable {MessageCountConfigKey} to the number of messages that should be sent (set it to -1 to send unlimited messages)."); TransportType transportType = configuration.GetValue("ClientTransportType", TransportType.Amqp_Tcp_Only); Console.WriteLine($"Using transport {transportType.ToString()}"); var retryPolicy = new RetryPolicy(TimeoutErrorDetectionStrategy, TransientRetryStrategy); retryPolicy.Retrying += (_, args) => { Console.WriteLine($"Creating ModuleClient failed with exception {args.LastException}"); if (args.CurrentRetryCount < RetryCount) { Console.WriteLine("Retrying..."); } }; ModuleClient moduleClient = await retryPolicy.ExecuteAsync(() => InitModuleClient(transportType)); ModuleClient userContext = moduleClient; await moduleClient.SetInputMessageHandlerAsync("control", ControlMessageHandle, userContext); (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), null); await SendEvents(moduleClient, messageDelay, sendForever, messageCount, sim, cts); await cts.Token.WhenCanceled(); completed.Set(); handler.ForEach(h => GC.KeepAlive(h)); return(0); }
static async Task <int> MainAsync() { Console.WriteLine($"[{DateTime.UtcNow.ToString("MM/dd/yyyy hh:mm:ss.fff tt", CultureInfo.InvariantCulture)}] Main()"); IConfiguration configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("config/appsettings.json", optional: true) .AddEnvironmentVariables() .Build(); TimeSpan messageDelay = configuration.GetValue("MessageDelay", TimeSpan.FromSeconds(5)); var sim = new SimulatorParameters { MachineTempMin = configuration.GetValue <double>("machineTempMin", 21), MachineTempMax = configuration.GetValue <double>("machineTempMax", 100), MachinePressureMin = configuration.GetValue <double>("machinePressureMin", 1), MachinePressureMax = configuration.GetValue <double>("machinePressureMax", 10), AmbientTemp = configuration.GetValue <double>("ambientTemp", 21), HumidityPercent = configuration.GetValue("ambientHumidity", 25) }; TransportType transportType = configuration.GetValue("ClientTransportType", TransportType.Amqp_Tcp_Only); Console.WriteLine($"Using transport {transportType.ToString()}"); var retryPolicy = new RetryPolicy(TimeoutErrorDetectionStrategy, TransientRetryStrategy); retryPolicy.Retrying += (_, args) => { Console.WriteLine($"Creating ModuleClient failed with exception {args.LastException}"); if (args.CurrentRetryCount < RetryCount) { Console.WriteLine("Retrying..."); } }; ModuleClient moduleClient = await retryPolicy.ExecuteAsync(() => InitModuleClient(transportType)); ModuleClient userContext = moduleClient; await moduleClient.SetInputMessageHandlerAsync("control", ControlMessageHandle, userContext).ConfigureAwait(false); (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), null); await SendEvents(moduleClient, messageDelay, sim, cts).ConfigureAwait(false); completed.Set(); handler.ForEach(h => GC.KeepAlive(h)); return(0); }
static async Task <int> MainAsync() { Console.WriteLine("SimulatedTemperatureSensor Main() started."); IConfiguration configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("config/appsettings.json", optional: true) .AddEnvironmentVariables() .Build(); messageDelay = configuration.GetValue("MessageDelay", TimeSpan.FromSeconds(5)); int messageCount = configuration.GetValue(MessageCountConfigKey, 500); var simulatorParameters = new SimulatorParameters { MachineTempMin = configuration.GetValue <double>("machineTempMin", 21), MachineTempMax = configuration.GetValue <double>("machineTempMax", 100), MachinePressureMin = configuration.GetValue <double>("machinePressureMin", 1), MachinePressureMax = configuration.GetValue <double>("machinePressureMax", 10), AmbientTemp = configuration.GetValue <double>("ambientTemp", 21), HumidityPercent = configuration.GetValue("ambientHumidity", 25) }; Console.WriteLine( $"Initializing simulated temperature sensor to send {(SendUnlimitedMessages(messageCount) ? "unlimited" : messageCount.ToString())} " + $"messages, at an interval of {messageDelay.TotalSeconds} seconds.\n" + $"To change this, set the environment variable {MessageCountConfigKey} to the number of messages that should be sent (set it to -1 to send unlimited messages)."); TransportType transportType = configuration.GetValue("ClientTransportType", TransportType.Amqp_Tcp_Only); ModuleClient moduleClient = await CreateModuleClientAsync( transportType, DefaultTimeoutErrorDetectionStrategy, DefaultTransientRetryStrategy); await moduleClient.OpenAsync(); await moduleClient.SetMethodHandlerAsync("reset", ResetMethod, null); (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), null); Twin currentTwinProperties = await moduleClient.GetTwinAsync(); if (currentTwinProperties.Properties.Desired.Contains(SendIntervalConfigKey)) { messageDelay = TimeSpan.FromSeconds((int)currentTwinProperties.Properties.Desired[SendIntervalConfigKey]); } if (currentTwinProperties.Properties.Desired.Contains(SendDataConfigKey)) { sendData = (bool)currentTwinProperties.Properties.Desired[SendDataConfigKey]; if (!sendData) { Console.WriteLine("Sending data disabled. Change twin configuration to start sending again."); } } ModuleClient userContext = moduleClient; await moduleClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertiesUpdated, userContext); await moduleClient.SetInputMessageHandlerAsync("control", ControlMessageHandle, userContext); await SendEvents(moduleClient, messageCount, simulatorParameters, cts); await cts.Token.WhenCanceled(); completed.Set(); handler.ForEach(h => GC.KeepAlive(h)); Console.WriteLine("SimulatedTemperatureSensor Main() finished."); return(0); }
static async Task <int> MainAsync() { Console.WriteLine("SimulatedTemperatureSensor Main() started."); var appSettings = ConfigurationManager.AppSettings; // Setup App Insights if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY"))) { Console.WriteLine("Application Insights Enabled."); insights = true; telemetryClient = new TelemetryClient(); telemetryClient.Context.Device.Id = Environment.MachineName; telemetryClient.TrackEvent("SimulatedTemperatureSensor started"); telemetryClient.GetMetric("SimulatorCount").TrackValue(1); } if (!TimeSpan.TryParse(appSettings["MessageDelay"], out messageDelay)) { messageDelay = TimeSpan.FromSeconds(5); } int messageCount; if (!int.TryParse(Environment.GetEnvironmentVariable(MessageCountConfigKey), out messageCount)) { if (!int.TryParse(appSettings[MessageCountConfigKey], out messageCount)) { messageCount = 500; } } var simulatorParameters = SimulatorParameters.Create(); Console.WriteLine( $"Initializing simulated sensor to send {(SendUnlimitedMessages(messageCount) ? "unlimited" : messageCount.ToString())} " + $"messages, at an interval of {messageDelay.TotalSeconds} seconds.\n" + $"To change this, set the environment variable {MessageCountConfigKey} to the number of messages that should be sent (set it to -1 to send unlimited messages)."); ModuleClient moduleClient = await ModuleUtil.CreateModuleClientAsync( TransportType.Amqp_Tcp_Only, ModuleUtil.DefaultTimeoutErrorDetectionStrategy, ModuleUtil.DefaultTransientRetryStrategy); await moduleClient.OpenAsync(); await moduleClient.SetMethodHandlerAsync("reset", ResetMethod, null); (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), null); Twin currentTwinProperties = await moduleClient.GetTwinAsync(); if (currentTwinProperties.Properties.Desired.Contains(SendIntervalConfigKey)) { messageDelay = TimeSpan.FromSeconds((int)currentTwinProperties.Properties.Desired[SendIntervalConfigKey]); } if (currentTwinProperties.Properties.Desired.Contains(SendDataConfigKey)) { sendData = (bool)currentTwinProperties.Properties.Desired[SendDataConfigKey]; if (!sendData) { Console.WriteLine("Sending data disabled. Change twin configuration to start sending again."); } } ModuleClient userContext = moduleClient; await moduleClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertiesUpdated, userContext); await moduleClient.SetInputMessageHandlerAsync("control", ControlMessageHandle, userContext); await SendEvents(moduleClient, messageCount, simulatorParameters, cts); await cts.Token.WhenCanceled(); completed.Set(); handler.ForEach(h => GC.KeepAlive(h)); Console.WriteLine("SimulatedTemperatureSensor Main() finished."); return(0); }
/// <summary> /// Module behavior: /// Sends data periodically (with default frequency of 5 seconds). /// Data trend: /// - Temperature regularly rises from 21C to 100C in regularly with jitter /// - Pressure correlates with Temperature 1 to 10psi /// - Suction Pressure stable around 5psi /// - Discharge Pressure stable around 5psi /// - Ambient temperature stable around 21C /// - Flow is stable with tiny jitter around 25% /// Method for resetting the data stream /// </summary> static async Task SendEvents( ModuleClient moduleClient, int messageCount, SimulatorParameters sim, CancellationTokenSource cts) { int count = 1; double currentTemp = sim.TempMin; double normal = (sim.PressureMax - sim.PressureMin) / (sim.TempMax - sim.TempMin); while (!cts.Token.IsCancellationRequested && (SendUnlimitedMessages(messageCount) || messageCount >= count)) { if (Reset) { currentTemp = sim.TempMin; Reset.Set(false); } if (currentTemp > sim.TempMax) { currentTemp += Rnd.NextDouble() - 0.5; // add value between [-0.5..0.5] } else { currentTemp += -0.25 + (Rnd.NextDouble() * 1.5); // add value between [-0.25..1.25] - average +0.5 } if (sendData) { var events = new List <MessageEvent>(); events.Add(new MessageEvent { DeviceId = Environment.GetEnvironmentVariable("DEVICE") ?? Environment.MachineName, TimeStamp = DateTime.UtcNow, Temperature = new SensorReading { Value = currentTemp, Units = "degC", Status = 192 }, Pressure = new SensorReading { Value = sim.PressureMin + ((currentTemp - sim.TempMin) * normal), Units = "psig", Status = 192 }, SuctionPressure = new SensorReading { Value = sim.PressureMin + 4 + ((currentTemp - sim.TempMin) * normal), Units = "psig", Status = 192 }, DischargePressure = new SensorReading { Value = sim.PressureMin + 1 + ((currentTemp - sim.TempMin) * normal), Units = "psig", Status = 192 }, Flow = new SensorReading { Value = Rnd.Next(78, 82), Units = "perc", Status = 192, Misc = "GOOD" } }); var tempData = new MessageBody { Asset = Environment.GetEnvironmentVariable("ASSET") ?? "PoC", Source = "Simulator", Events = events }; string dataBuffer = JsonConvert.SerializeObject(tempData); var eventMessage = new Message(Encoding.UTF8.GetBytes(dataBuffer)); eventMessage.Properties.Add("sequenceNumber", count.ToString()); eventMessage.Properties.Add("batchId", BatchId.ToString()); eventMessage.Properties.Add("asset", tempData.Asset); Console.WriteLine($"\t{DateTime.Now.ToLocalTime()}> Sending message: {count}, Body: [{dataBuffer}]"); await moduleClient.SendEventAsync("temperatureOutput", eventMessage); if (insights) { telemetryClient.GetMetric("SendEvent").TrackValue(1); } count++; } await Task.Delay(messageDelay, cts.Token); } if (messageCount < count) { Console.WriteLine($"Done sending {messageCount} messages"); } }