/// <summary> /// Creates a environmental data provider from configuration. /// </summary> /// <param name="configuration">The configuration to get provider info from.</param> /// <param name="factor">The factor to create a provider for.</param> /// <returns>Returns a provider or null.</returns> /// <exception cref="System.Exception">An invalid provider name `{providerName}` was supplied for factor `{factor.ToString().ToLower()}`.</exception> private static IEnvironmentFactorProvider CreateProvider(IConfiguration configuration, Factor factor) { string providerName = configuration.GetValue($"{factor.ToString()}:Provider", ""); if (string.IsNullOrWhiteSpace(providerName)) { Console.WriteLine($"No provider configured for factor `{factor.ToString().ToLower()}`, ignoring..."); return(null); } else { IEnvironmentFactorProvider provider = null; switch (providerName) { case "MockTemperatureProvider": provider = new MockTemperatureProvider(configuration.GetSection($"{factor.ToString()}:Configuration")); break; case "MockHumidityProvider": provider = new MockHumidityProvider(configuration.GetSection($"{factor.ToString()}:Configuration")); break; default: throw new Exception($"An invalid provider name `{providerName}` was supplied for factor `{factor.ToString().ToLower()}`."); } Console.WriteLine($"Configuring provider `{providerName}` for factor `{factor.ToString().ToLower()}`."); return(provider); } }
/// <summary> /// Starts periodically reading data. /// <paramref name="cancellationTokenSource"/> /// </summary> public void StartReading(CancellationTokenSource cancellationTokenSource) { if (ReadLoop == null) { ReadLoop = new TaskFactory().StartNew(async() => { try { while (!cancellationTokenSource.IsCancellationRequested) { DataPoint dataPoint = new DataPoint() { Timestamp = DateTime.UtcNow, Temperature = null, Humidity = null }; IEnvironmentFactorProvider provider = null; if (Providers.TryGetValue(Factor.Temperature, out provider)) { dataPoint.Temperature = provider.Read(); } if (Providers.TryGetValue(Factor.Humidity, out provider)) { dataPoint.Humidity = provider.Read(); } try { string message = JsonConvert.SerializeObject(dataPoint); using (IProducer <Null, string> producer = new ProducerBuilder <Null, string>(ProducerConfig).Build()) { DeliveryResult <Null, string> result = await producer.ProduceAsync(Topic, new Message <Null, string> { Value = message }); Console.WriteLine($" + Delivered '{result.Value}' to '{Topic}'"); } } catch (ProduceException <Null, string> exception) { Console.WriteLine($" + Delivery failed: {exception.Error.Reason}"); } catch (Exception exception) { Console.WriteLine($"Kafka error: {exception}"); } await Task.Delay(ReadInterval, cancellationTokenSource.Token); } } catch (TaskCanceledException) { } finally { Console.WriteLine("Environment handler terminating..."); } }, TaskCreationOptions.LongRunning); } }
/// <summary> /// Registers a new data provider. /// </summary> /// <param name="factor">The factor that provider provides data for.</param> /// <param name="provider">The provider.</param> public void RegisterProvider(Factor factor, IEnvironmentFactorProvider provider) { Providers.Add(factor, provider); }
/// <summary> /// Program entry points. Parses config, initializes providers and starts a handler. /// </summary> static void Main(string[] args) { ConsoleKeyInfo ConsoleKeyInfo; Console.TreatControlCAsInput = true; // Read config files IConfiguration configuration = new ConfigurationBuilder() .AddJsonFile("./appsettings.json") .AddJsonFile("./appsettings.Development.json", true).Build(); // Get and validate Kafka server endpoint string kafkaEndpoint = configuration.GetValue("Kafka", ""); if (string.IsNullOrWhiteSpace(kafkaEndpoint)) { throw new Exception("No valid Kafka endpoint was provided."); } else { Console.WriteLine($"Configuring Kafka endpoint `{kafkaEndpoint}`..."); } // Get and validate topic string topic = configuration.GetValue("Topic", ""); if (string.IsNullOrWhiteSpace(topic)) { throw new Exception("No valid Kafka topic name was provided."); } else { Console.WriteLine($"Configuring Kafka topic `{topic}`..."); } // Get and validate read interval int readIntervalInSeconds = configuration.GetValue("ReadIntervalInSeconds", 10); if (readIntervalInSeconds <= 0) { throw new Exception("No valid read interval was provided."); } else { Console.WriteLine($"Configuring a read interval of `{readIntervalInSeconds}` seconds..."); } TimeSpan readInterval = TimeSpan.FromSeconds(readIntervalInSeconds); // Create handler EnvironmentHandler handler = new EnvironmentHandler(kafkaEndpoint, topic, readInterval); // Temperature provider IEnvironmentFactorProvider temperatureProvider = CreateProvider(configuration, Factor.Temperature); if (temperatureProvider != null) { handler.RegisterProvider(Factor.Temperature, temperatureProvider); } // Humidity provider IEnvironmentFactorProvider humidityProvider = CreateProvider(configuration, Factor.Humidity); if (humidityProvider != null) { handler.RegisterProvider(Factor.Humidity, humidityProvider); } // Check for any provider... if (!handler.GetTrackedFactors().Any()) { throw new Exception("No providers loaded, terminating..."); } // Start reading data! CancellationTokenSource cancellationTokenSoruce = new CancellationTokenSource(); handler.StartReading(cancellationTokenSoruce); // Wait for CTRL+C termination do { Console.WriteLine("Please enter CTRL+C to terminate..."); ConsoleKeyInfo = Console.ReadKey(true); } while ((ConsoleKeyInfo.Modifiers & ConsoleModifiers.Control) == 0 || ConsoleKeyInfo.Key != ConsoleKey.C); Console.WriteLine("Cancellation was requested, waiting for environment handler to terminate..."); cancellationTokenSoruce.Cancel(); Thread.Sleep(readInterval); }