public bool IsValid()
        {
            bool ret = true;

            // SensorDevicePath must be present, publish interval must be positive
            if (string.IsNullOrEmpty(SensorDevicePath))
            {
                Console.WriteLine("Missing or empty value for SensorDevicePath");
                ret = false;
            }
            else if (PublishIntervalSeconds <= 0)
            {
                Console.WriteLine("Invalid value for PublishIntervalSeconds: ", PublishIntervalSeconds);
                ret = false;
            }
            else
            {
                // Validate individual sensor configs
                foreach (var config_pair in SensorConfigs)
                {
                    SensorConfig sensorConfig = config_pair.Value;
                    // The only absolutely required field is the 1Wire ID for the sensor
                    if (string.IsNullOrEmpty(sensorConfig.SensorId))
                    {
                        Console.WriteLine("Key: ", config_pair.Key, ": Missing or empty value for SensorId");
                        ret = false;
                        break;
                    }
                }
            }
            return(ret);
        }
        public SensorReading(ModuleConfig mc, string sensorId)
        {
            SensorConfig sc = mc.SensorConfigs[sensorId];

            PublishTimestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            SensorName       = string.IsNullOrEmpty(sc.SensorName) ? ModuleConfigDefaults.DefaultSensorName : sc.SensorName;
            UOM         = string.IsNullOrEmpty(sc.UOM) ? ModuleConfigDefaults.DefaultSensorUOM : sc.UOM;
            Temperature = -9999;

            string sensorfile   = mc.SensorDevicePath + sc.SensorId + mc.SensorDevicePathSuffix;
            bool   deviceReadOk = false;

            if (mc.VerboseLogging)
            {
                Console.WriteLine("Opening file: " + sensorfile);
            }
            // Open the sensor file
            string[] lines = { "NO", "READING=-9999" };
            try
            {
                lines        = System.IO.File.ReadAllLines(sensorfile);
                deviceReadOk = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Unable to read device file " + sensorfile + ": " + ex.Message);
            }

            if (deviceReadOk)
            {
                // DS18B20 device files have the following structure:
                // Line 1: Status
                // Line 2: Reading
                // Status will be YES if the reading is valid, if it's not YES then we should report an error
                // Reading takes the form of string=number, where number is the Celcius temperature in thousandths of a degree

                if (lines[0].Contains("YES"))
                {
                    string[] readingString = lines[1].Split('=');
                    float    readingC1000  = Convert.ToSingle(readingString[1]);
                    Temperature = readingC1000 / (float)1000.0;
                    if (sc.UOM.Equals("F"))
                    {
                        Temperature = (float)32 + ((float)1.8 * Temperature);
                    }
                }
            }
        }