public static HashSet <IEvaluableSensor> LoadSensorsInformationFromString(string input, ref decimal refTemperature, ref decimal refHumidity, ref int refCarbonMonoxide, string separator = " ")
        {
            HashSet <IEvaluableSensor> sensors = new HashSet <IEvaluableSensor>();

            string[] lines = input.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);

            if (lines.Length == 0)
            {
                return(sensors);
            }

            string[] referenceValuesRow = lines[0].Split(separator);

            if (!decimal.TryParse(referenceValuesRow[1], NumberStyles.Any, CultureInfo.GetCultureInfo("cz-CZ"), out refTemperature))
            {
                throw new Exception($"Unexpected reference value for Temperature: {referenceValuesRow[1]}, decimal is expected.");
            }
            if (!decimal.TryParse(referenceValuesRow[2], NumberStyles.Any, CultureInfo.GetCultureInfo("cz-CZ"), out refHumidity))
            {
                throw new Exception($"Unexpected reference value for Humidity: {referenceValuesRow[2]}, decimal is expected.");
            }
            if (!int.TryParse(referenceValuesRow[3], out refCarbonMonoxide))
            {
                throw new Exception($"Unexpected reference value for Carbon Monoxide: {referenceValuesRow[3]}, integet is expected.");
            }

            string[] sensorsData = lines.Skip(1).ToArray();

            IEvaluableSensor currentSensor = null;
            DateTime         timeOfMeasurement;

            foreach (string line in sensorsData)
            {
                string[] splittedLine = line.Split(separator);
                if (Constants.SensorTypes.Contains(splittedLine[0]))
                {
                    if (currentSensor != null)
                    {
                        sensors.Add(currentSensor);
                    }

                    switch (splittedLine[0])
                    {
                    case Constants.ThermometerTypeNameInLog:
                        currentSensor = new Thermometer();
                        break;

                    case Constants.HumiditySensorTypeNameInLog:
                        currentSensor = new HumiditySensor();
                        break;

                    case Constants.CarbonMonoxideSensorTypeNameInLog:
                        currentSensor = new CarbonMonoxideDetector();
                        break;

                    default:
                        break;
                    }

                    currentSensor.Name = splittedLine[1];
                }
                else
                {
                    if (!DateTime.TryParse(splittedLine[0], out timeOfMeasurement))
                    {
                        throw new Exception($"Sensor: {currentSensor.Name} has reading with unexpected DateTime format: {splittedLine[0]}");
                    }
                    currentSensor.AddReading(timeOfMeasurement, splittedLine[1]);
                }
            }

            if (currentSensor != null)
            {
                sensors.Add(currentSensor);
            }
            return(sensors);
        }
        public void CarbonMonoxideDetector_FromDynamic_ShouldReturnExpectedResult(InstalledAppInstance installedApp)
        {
            var expectedResult = new CarbonMonoxideDetector()
            {
                Id           = Guid.NewGuid().ToString(),
                Label        = "MyDevice",
                CurrentState = CarbonMonoxideState.Clear
            };

            var deviceJson = $@"{{
                ""deviceId"": ""{expectedResult.Id}"",
                ""name"": ""NAME"",
                ""label"": ""{expectedResult.Label}"",
                ""locationId"": ""{installedApp.InstalledLocation.Id}""
            }}";

            var statusJson = $@"{{
                ""deviceId"": ""{expectedResult.Id}"",
                ""name"": ""NAME"",
                ""label"": ""{expectedResult.Label}"",
                ""locationId"": ""{installedApp.InstalledLocation.Id}"",
                ""components"" : {{
                    ""main"": {{
                        ""carbonMonoxideDetector"": {{
                            ""carbonMonoxide"": {{
                                ""value"": ""clear""
                            }}
                        }}
                    }}
                }}
            }}";

            dynamic device = JObject.Parse(deviceJson);
            dynamic status = JObject.Parse(statusJson);

            var result = CarbonMonoxideDetector.CarbonMonoxideDetectorFromDynamic(device,
                                                                                  status);

            Assert.Equal(expectedResult, result);

            expectedResult.CurrentState = CarbonMonoxideState.Detected;
            statusJson = $@"{{
                ""deviceId"": ""{expectedResult.Id}"",
                ""name"": ""NAME"",
                ""label"": ""{expectedResult.Label}"",
                ""locationId"": ""{installedApp.InstalledLocation.Id}"",
                ""components"" : {{
                    ""main"": {{
                        ""carbonMonoxideDetector"": {{
                            ""carbonMonoxide"": {{
                                ""value"": ""detected""
                            }}
                        }}
                    }}
                }}
            }}";

            status = JObject.Parse(statusJson);

            result = CarbonMonoxideDetector.CarbonMonoxideDetectorFromDynamic(device,
                                                                              status);

            Assert.Equal(expectedResult, result);

            expectedResult.CurrentState = CarbonMonoxideState.Tested;
            statusJson = $@"{{
                ""deviceId"": ""{expectedResult.Id}"",
                ""name"": ""NAME"",
                ""label"": ""{expectedResult.Label}"",
                ""locationId"": ""{installedApp.InstalledLocation.Id}"",
                ""components"" : {{
                    ""main"": {{
                        ""carbonMonoxideDetector"": {{
                            ""carbonMonoxide"": {{
                                ""value"": ""tested""
                            }}
                        }}
                    }}
                }}
            }}";

            status = JObject.Parse(statusJson);

            result = CarbonMonoxideDetector.CarbonMonoxideDetectorFromDynamic(device,
                                                                              status);

            Assert.Equal(expectedResult, result);

            expectedResult.CurrentState = CarbonMonoxideState.Unknown;
            statusJson = $@"{{
                ""deviceId"": ""{expectedResult.Id}"",
                ""name"": ""NAME"",
                ""label"": ""{expectedResult.Label}"",
                ""locationId"": ""{installedApp.InstalledLocation.Id}"",
                ""components"" : {{
                    ""main"": {{
                        ""carbonMonoxideDetector"": {{
                            ""carbonMonoxide"": {{
                                ""value"": ""unknown""
                            }}
                        }}
                    }}
                }}
            }}";

            status = JObject.Parse(statusJson);

            result = CarbonMonoxideDetector.CarbonMonoxideDetectorFromDynamic(device,
                                                                              status);

            Assert.Equal(expectedResult, result);

            _ = expectedResult.GetHashCode();
            _ = expectedResult.ToJson();
        }