Example #1
0
 private void ProcessExtraDewPoint(NameValueCollection data, WeatherStation station)
 {
     for (var i = 1; i <= 10; i++)
     {
         if (data["temp" + i + "f"] != null && data["humidity" + i] != null)
         {
             var dp = MeteoLib.DewPoint(ConvertUserTempToC(station.ExtraTemp[i]), station.ExtraHum[i]);
             station.ExtraDewPoint[i] = ConvertTempCToUser(dp);
         }
     }
 }
Example #2
0
        private void ImetGetData()
        {
            const int TEMP1POS  = 1;
            const int TEMP2POS  = 2;
            const int RELHUMPOS = 3;
            const int PRESSPOS  = 4;
            const int WINDPOS   = 5;
            const int DIRPOS    = 6;
            const int SUNPOS    = 7;
            const int RAINPOS   = 8;
            //const int CHECKSUMPOS = 9;

            DateTime now = DateTime.Now;

            int h   = now.Hour;
            int min = now.Minute;

            if (min != previousminute)
            {
                previousminute = min;

                if (cumulus.StationOptions.SyncTime && (h == cumulus.StationOptions.ClockSettingHour) && (min == 2))
                {
                    // It's 0400, set the station clock
                    SetStationClock();
                }
            }

            SendCommand("RDLV");
            // read the response
            var response = GetResponse("rdlv");

            if (ValidChecksum(response) && !stop)
            {
                // split the data
                var sl = new List <string>(Regex.Split(response, ","));

                if (sl.Count != 10 && sl[0] != "rdlv")
                {
                    cumulus.LogMessage($"RDLV: Unexpected response: {response}");
                    return;
                }

                // Parse data using decimal points rather than user's decimal separator
                NumberFormatInfo provider = new NumberFormatInfo {
                    NumberDecimalSeparator = "."
                };

                double windspeed = -999;
                double temp1     = -999;
                int    humidity  = -999;

                double varDbl;
                int    varInt;

                if (!string.IsNullOrEmpty(sl[DIRPOS]) && int.TryParse(sl[DIRPOS], out varInt) &&
                    !string.IsNullOrEmpty(sl[WINDPOS]) && double.TryParse(sl[WINDPOS], NumberStyles.Float, provider, out varDbl))
                {
                    windspeed = varDbl;
                    DoWind(ConvertWindMSToUser(windspeed), varInt, ConvertWindMSToUser(windspeed), now);
                }
                else
                {
                    cumulus.LogMessage($"RDLV: Unexpected wind dir/speed format, found: {sl[DIRPOS]}/{sl[WINDPOS]}");
                }


                if (!string.IsNullOrEmpty(sl[TEMP1POS]) && double.TryParse(sl[TEMP1POS], NumberStyles.Float, provider, out varDbl))
                {
                    temp1 = varDbl;
                    DoOutdoorTemp(ConvertTempCToUser(temp1), now);
                    if (windspeed > -99)
                    {
                        double windchill = MeteoLib.WindChill(temp1, windspeed * 3.6);
                        DoWindChill(windchill, now);
                    }
                }
                else
                {
                    cumulus.LogMessage($"RDLV: Unexpected temperature 1 format, found: {sl[TEMP1POS]}");
                }

                if (!string.IsNullOrEmpty(sl[TEMP2POS]))                  // TEMP2 is optional
                {
                    if (double.TryParse(sl[TEMP2POS], NumberStyles.Float, provider, out varDbl))
                    {
                        if (cumulus.StationOptions.LogExtraSensors)
                        {
                            // use second temp as Extra Temp 1
                            DoExtraTemp(ConvertTempCToUser(varDbl), 1);
                        }
                        else
                        {
                            // use second temp as wet bulb
                            DoWetBulb(ConvertTempCToUser(varDbl), now);
                        }
                    }
                    else
                    {
                        cumulus.LogMessage($"RDLV: Unexpected temperature 2 format, found: {sl[TEMP2POS]}");
                    }
                }

                if (!string.IsNullOrEmpty(sl[RELHUMPOS]) && double.TryParse(sl[RELHUMPOS], NumberStyles.Float, provider, out varDbl))
                {
                    humidity = Convert.ToInt32(varDbl);
                    DoOutdoorHumidity(humidity, now);
                }
                else
                {
                    cumulus.LogMessage($"RDLV: Unexpected humidity format, found: {sl[RELHUMPOS]}");
                }

                if (!string.IsNullOrEmpty(sl[PRESSPOS]) && double.TryParse(sl[PRESSPOS], NumberStyles.Float, provider, out varDbl))
                {
                    DoPressure(ConvertPressMBToUser(varDbl), now);
                    UpdatePressureTrendString();
                }
                else
                {
                    cumulus.LogMessage($"RDLV: Unexpected pressure format, found: {sl[PRESSPOS]}");
                }


                if (!string.IsNullOrEmpty(sl[RAINPOS]) && double.TryParse(sl[RAINPOS], NumberStyles.Float, provider, out varDbl))
                {
                    DoRain(ConvertRainMMToUser(varDbl), -1, now);
                }
                else
                {
                    cumulus.LogMessage($"RDLV: Unexpected rain format, found: {sl[RAINPOS]}");
                }

                if (!string.IsNullOrEmpty(sl[SUNPOS]) && double.TryParse(sl[SUNPOS], NumberStyles.Float, provider, out varDbl))
                {
                    DoSunHours(varDbl);
                }
                else
                {
                    cumulus.LogMessage($"RDLV: Unexpected rain format, found: {sl[RAINPOS]}");
                }

                if (temp1 > -999 && humidity > -999)
                {
                    DoOutdoorDewpoint(0, now);
                    DoHumidex(now);
                    DoCloudBaseHeatIndex(now);

                    if (windspeed > -999)
                    {
                        DoApparentTemp(now);
                        DoFeelsLike(now);
                    }
                }

                DoForecast("", false);

                UpdateStatusPanel(now);
                UpdateMQTT();
            }
            else
            {
                cumulus.LogMessage("RDLV: Invalid checksum:");
                cumulus.LogMessage(response);
            }

            if (!cumulus.ImetOptions.UpdateLogPointer || stop)
            {
                return;
            }

            // Keep the log pointer current, to avoid large numbers of logs
            // being downloaded at next start-up
            // Only do this every 30 read intervals
            if (readCounter > 0)
            {
                readCounter--;
            }
            else
            {
                UpdateReadPointer();
                readCounter = 30;
            }
        }
Example #3
0
        public override void getAndProcessHistoryData()
        {
            // Positions of fields in logger data
            //const int IDPOS = 1;
            //const int TYPEPOS = 2;
            const int INTERVALPOS = 3;
            const int TIMEPOS     = 4;
            const int DATEPOS     = 5;
            //const int TEMP1MINPOS = 6;
            //const int TEMP1MAXPOS = 7;
            const int TEMP1AVGPOS = 8;
            //const int TEMP2MINPOS = 9;
            //const int TEMP2MAXPOS = 10;
            const int TEMP2AVGPOS = 11;
            //const int RELHUMMINPOS = 12;
            //const int RELHUMMAXPOS = 13;
            const int RELHUMAVGPOS = 14;
            //const int PRESSMINPOS = 15;
            //const int PRESSMAXPOS = 16;
            const int PRESSAVGPOS = 17;
            //const int WINDMINPOS = 18;
            const int WINDMAXPOS = 19;
            const int WINDAVGPOS = 20;
            const int DIRPOS     = 21;
            const int SUNPOS     = 22;
            const int RAINPOS    = 23;

            DateTime timestamp = DateTime.MinValue;

            NumberFormatInfo provider = new NumberFormatInfo {
                NumberDecimalSeparator = "."
            };

            DateTime startfrom  = cumulus.LastUpdateTime;
            int      startindex = 0;
            int      year       = startfrom.Year;
            int      month      = startfrom.Month;
            int      day        = startfrom.Day;
            int      hour       = startfrom.Hour;
            int      minute     = startfrom.Minute;
            int      sec        = startfrom.Second;

            cumulus.LogMessage($"Last update time = {year}/{month}/{day} {hour}:{minute}:{sec}");

            int recordsdone = 0;

            if (FirstRun)
            {
                // First time Cumulus has run, "delete" all the log entries as there may be
                // vast numbers and they will take hours to download only to be discarded

                //cumulus.LogMessage("First run: PRLG,32760");
                // regress the pointer
                //comport.Write("PRLG,32760" + sLineBreak);
                // read the response
                //response = GetResponse("prlg");

                // Do it by updating the read pointer to match the write pointer
                // The recorded value for currentWritePointer will not have been set yet
                UpdateReadPointer();
            }

            cumulus.LogMessage("Downloading history from " + startfrom);
            cumulus.LogConsoleMessage("Reading archive data from " + startfrom + " - please wait");
            //RegressLogs(cumulus.LastUpdateTime);
            //bool valid = false;
            int numrecs = GetNumberOfLogs();

            cumulus.LogMessage("Logs available = " + numrecs);
            if (numrecs > 0)
            {
                cumulus.LogMessage("Number of history records = " + numrecs);
                // get the earliest record
                List <string> sl = GetArchiveRecord();
                bool          dataOK;
                try
                {
                    hour   = Convert.ToInt32(sl[TIMEPOS].Substring(0, 2));
                    minute = Convert.ToInt32(sl[TIMEPOS].Substring(3, 2));
                    sec    = Convert.ToInt32(sl[TIMEPOS].Substring(6, 2));
                    day    = Convert.ToInt32(sl[DATEPOS].Substring(0, 2));
                    month  = Convert.ToInt32(sl[DATEPOS].Substring(3, 2));
                    year   = Convert.ToInt32(sl[DATEPOS].Substring(6, 4));
                    cumulus.LogMessage("Logger entry : Y = " + year + ", M = " + month + ", D = " + day + ", h = " + hour + ", m = " + minute + ", s = " + sec);

                    timestamp = new DateTime(year, month, day, hour, minute, sec, 0);
                    dataOK    = true;
                }
                catch
                {
                    cumulus.LogMessage("Error in earliest timestamp, unable to process logger data");
                    dataOK = false;
                }

                if (dataOK)
                {
                    cumulus.LogMessage("Earliest timestamp " + timestamp);
                    if (timestamp < cumulus.LastUpdateTime)
                    {
                        // startindex = 1;
                        cumulus.LogMessage("-----Earliest timestamp is earlier than required");
                        cumulus.LogMessage("-----Find first entry after " + cumulus.LastUpdateTime);
                        startindex++;                         //  to allow for first log already read
                        while ((startindex < numrecs) && (timestamp <= cumulus.LastUpdateTime))
                        {
                            // Move on to next entry
                            ProgressLogs();
                            sl = GetArchiveRecord();
                            try
                            {
                                hour   = Convert.ToInt32(sl[TIMEPOS].Substring(0, 2));
                                minute = Convert.ToInt32(sl[TIMEPOS].Substring(3, 2));
                                sec    = Convert.ToInt32(sl[TIMEPOS].Substring(6, 2));
                                day    = Convert.ToInt32(sl[DATEPOS].Substring(0, 2));
                                month  = Convert.ToInt32(sl[DATEPOS].Substring(3, 2));
                                year   = Convert.ToInt32(sl[DATEPOS].Substring(6, 4));
                                cumulus.LogMessage("Logger entry zero: Y = " + year + ", M = " + month + ", D = " + day + ", h = " + hour + ", m = " + minute + ", s = " + sec);

                                timestamp = new DateTime(year, month, day, hour, minute, sec, 0);
                                cumulus.LogMessage("New earliest timestamp " + timestamp);
                            }
                            catch (Exception E)
                            {
                                cumulus.LogMessage("Error in timestamp, skipping entry. Error = " + E.Message);
                                timestamp = DateTime.MinValue;
                            }

                            startindex++;
                        }
                    }
                }

                if (startindex < numrecs)
                {
                    // We still have entries to process
                    cumulus.LogMessage("-----Actual number of valid history records = " + (numrecs - startindex));
                    // Compare earliest timestamp with the update time of the today file
                    // and see if (they are on the same day
                    //int hourInc = cumulus.GetHourInc();

                    // set up controls for end of day roll-over
                    int rollHour;
                    if (cumulus.RolloverHour == 0)
                    {
                        rollHour = 0;
                    }
                    else if (cumulus.Use10amInSummer && (TimeZoneInfo.Local.IsDaylightSavingTime(DateTime.Now)))
                    {
                        // Locale is currently on Daylight time
                        rollHour = cumulus.RolloverHour + 1;
                    }
                    else
                    {
                        // Locale is currently on Standard time or unknown
                        rollHour = cumulus.RolloverHour;
                    }

                    // Check to see if (today"s roll-over has been done
                    // (we might be starting up in the roll-over hour)

                    int luhour = cumulus.LastUpdateTime.Hour;

                    var rolloverdone = luhour == rollHour;

                    midnightraindone = luhour == 0;

                    for (int i = startindex; i < numrecs; i++)
                    {
                        try
                        {
                            recordsdone++;
                            sl = GetArchiveRecord();
                            ProgressLogs();

                            hour      = Convert.ToInt32(sl[TIMEPOS].Substring(0, 2));
                            minute    = Convert.ToInt32(sl[TIMEPOS].Substring(3, 2));
                            sec       = Convert.ToInt32(sl[TIMEPOS].Substring(6, 2));
                            day       = Convert.ToInt32(sl[DATEPOS].Substring(0, 2));
                            month     = Convert.ToInt32(sl[DATEPOS].Substring(3, 2));
                            year      = Convert.ToInt32(sl[DATEPOS].Substring(6, 4));
                            timestamp = new DateTime(year, month, day, hour, minute, sec);
                            cumulus.LogMessage("Processing logger data entry " + i + " for " + timestamp);

                            int interval = (int)(Convert.ToDouble(sl[INTERVALPOS], provider) / 60);
                            // Check for roll-over

                            if (hour != rollHour)
                            {
                                rolloverdone = false;
                            }

                            if (hour != 0)
                            {
                                midnightraindone = false;
                            }

                            if (sl[RELHUMAVGPOS].Length > 0)
                            {
                                DoOutdoorHumidity((int)(Convert.ToDouble(sl[RELHUMAVGPOS], provider)), timestamp);
                            }

                            if ((sl[WINDAVGPOS].Length > 0) && (sl[WINDMAXPOS].Length > 0) && (sl[DIRPOS].Length > 0))
                            {
                                double windspeed   = Convert.ToDouble(sl[WINDAVGPOS], provider);
                                double windgust    = Convert.ToDouble(sl[WINDMAXPOS], provider);
                                int    windbearing = Convert.ToInt32(sl[DIRPOS]);

                                DoWind(windgust, windbearing, windspeed, timestamp);

                                // add in "archivePeriod" minutes worth of wind speed to windrun
                                WindRunToday += ((WindAverage * WindRunHourMult[cumulus.Units.Wind] * interval) / 60.0);

                                DateTime windruncheckTS;
                                if ((hour == rollHour) && (minute == 0))
                                // this is the last logger entry before roll-over
                                // fudge the timestamp to make sure it falls in the previous day
                                {
                                    windruncheckTS = timestamp.AddMinutes(-1);
                                }
                                else
                                {
                                    windruncheckTS = timestamp;
                                }

                                CheckForWindrunHighLow(windruncheckTS);

                                // update dominant wind bearing
                                CalculateDominantWindBearing(Bearing, WindAverage, interval);
                            }

                            if (sl[TEMP1AVGPOS].Length > 0)
                            {
                                DoOutdoorTemp(ConvertTempCToUser(Convert.ToDouble(sl[TEMP1AVGPOS], provider)), timestamp);

                                // add in "archivePeriod" minutes worth of temperature to the temp samples
                                tempsamplestoday += interval;
                                TempTotalToday   += (OutdoorTemperature * interval);

                                // update chill hours
                                if (OutdoorTemperature < cumulus.ChillHourThreshold)
                                {
                                    // add 1 minute to chill hours
                                    ChillHours += interval / 60.0;
                                }

                                // update heating/cooling degree days
                                UpdateDegreeDays(interval);
                            }

                            if (sl[TEMP2AVGPOS].Length > 0)
                            {
                                double temp2 = Convert.ToDouble(sl[TEMP2AVGPOS], provider);
                                // supply in CELSIUS
                                if (cumulus.StationOptions.LogExtraSensors)
                                {
                                    DoExtraTemp(temp2, 1);
                                }
                                else
                                {
                                    DoWetBulb(temp2, timestamp);
                                }
                            }

                            if (sl[RAINPOS].Length > 0)
                            {
                                var    raintotal = Convert.ToDouble(sl[RAINPOS], provider);
                                double raindiff;
                                if (prevraintotal == -1)
                                {
                                    raindiff = 0;
                                }
                                else
                                {
                                    raindiff = raintotal - prevraintotal;
                                }

                                double rainrate = ConvertRainMMToUser((raindiff) * (60.0 / cumulus.logints[cumulus.DataLogInterval]));

                                DoRain(ConvertRainMMToUser(raintotal), rainrate, timestamp);

                                prevraintotal = raintotal;
                            }

                            if ((sl[WINDAVGPOS].Length > 0) && (sl[TEMP1AVGPOS].Length > 0))
                            {
                                // wind chill
                                double tempinC   = ConvertUserTempToC(OutdoorTemperature);
                                double windinKPH = ConvertUserWindToKPH(WindAverage);
                                double value     = MeteoLib.WindChill(tempinC, windinKPH);
                                // value is now in Celsius, convert to units in use
                                value = ConvertTempCToUser(value);
                                DoWindChill(value, timestamp);
                            }

                            if (sl[PRESSAVGPOS].Length > 0)
                            {
                                DoPressure(ConvertPressMBToUser(Convert.ToDouble(sl[PRESSAVGPOS], provider)), timestamp);
                            }

                            // Cause wind chill calc
                            DoWindChill(0, timestamp);

                            DoOutdoorDewpoint(0, timestamp);
                            DoApparentTemp(timestamp);
                            DoFeelsLike(timestamp);
                            DoHumidex(timestamp);
                            DoCloudBaseHeatIndex(timestamp);

                            // sunshine hours
                            if (sl[SUNPOS].Length > 0)
                            {
                                DoSunHours(Convert.ToDouble(sl[SUNPOS], provider));
                            }

                            cumulus.DoLogFile(timestamp, false);
                            cumulus.MySqlRealtimeFile(999, false, timestamp);

                            AddRecentDataEntry(timestamp, WindAverage, RecentMaxGust, WindLatest, Bearing, AvgBearing, OutdoorTemperature, WindChill, OutdoorDewpoint, HeatIndex,
                                               OutdoorHumidity, Pressure, RainToday, SolarRad, UV, Raincounter, FeelsLike, Humidex, ApparentTemperature, IndoorTemperature, IndoorHumidity, CurrentSolarMax, RainRate, -1, -1);
                            DoTrendValues(timestamp);

                            if (cumulus.StationOptions.CalculatedET && timestamp.Minute == 0)
                            {
                                // Start of a new hour, and we want to calculate ET in Cumulus
                                CalculateEvaoptranspiration(timestamp);
                            }

                            UpdatePressureTrendString();
                            UpdateStatusPanel(timestamp);

                            // Add current data to the lists of web service updates to be done
                            cumulus.AddToWebServiceLists(timestamp);

                            if ((hour == rollHour) && !rolloverdone)
                            {
                                // do roll-over
                                cumulus.LogMessage("Day roll-over " + timestamp);
                                DayReset(timestamp);

                                rolloverdone = true;
                            }

                            if ((hour == 0) && !midnightraindone)
                            {
                                ResetMidnightRain(timestamp);
                                ResetSunshineHours(timestamp);
                                ResetMidnightTemperatures(timestamp);
                                midnightraindone = true;
                            }
                        }
                        catch (Exception E)
                        {
                            cumulus.LogMessage("Error in data: " + E.Message);
                        }
                    }
                }
                else
                {
                    cumulus.LogMessage("No history records to process");
                }
            }
            else
            {
                cumulus.LogMessage("No history records to process");
            }
        }
Example #4
0
        /// <summary>
        ///     Read current data and process it
        /// </summary>
        private void GetAndProcessData()
        {
            //   Curr Reading Loc
            // 0  Time Since Last Save
            // 1  Hum In
            // 2  Temp In
            // 3  "
            // 4  Hum Out
            // 5  Temp Out
            // 6  "
            // 7  Pressure
            // 8  "
            // 9  Wind Speed m/s
            // 10  Wind Gust m/s
            // 11  Speed and Gust top nibbles (Gust top nibble)
            // 12  Wind Dir
            // 13  Rain counter
            // 14  "
            // 15  status

            // 16 Solar (Lux)
            // 17 "
            // 18 "
            // 19 UV

            //var ci = new CultureInfo("en-GB");
            //System.Threading.Thread.CurrentThread.CurrentCulture = ci;


            var data = new byte[32];

            if (cumulus.SyncFOReads && !Synchronising)
            {
                if ((DateTime.Now - FOSensorClockTime).TotalDays > 1)
                {
                    // (re)synchronise data reads to try to avoid USB lockup problem

                    StartSynchronising();

                    return;
                }
                else
                {
                    // Check that were not within N seconds of the station updating memory
                    bool sensorclockOK = ((int)(Math.Floor((DateTime.Now - FOSensorClockTime).TotalSeconds)) % 48 >= (cumulus.FOReadAvoidPeriod - 1)) &&
                                         ((int)(Math.Floor((DateTime.Now - FOSensorClockTime).TotalSeconds)) % 48 <= (47 - cumulus.FOReadAvoidPeriod));
                    bool stationclockOK = ((int)(Math.Floor((DateTime.Now - FOStationClockTime).TotalSeconds)) % 60 >= (cumulus.FOReadAvoidPeriod - 1)) &&
                                          ((int)(Math.Floor((DateTime.Now - FOStationClockTime).TotalSeconds)) % 60 <= (59 - cumulus.FOReadAvoidPeriod));

                    if (!sensorclockOK || !stationclockOK)
                    {
                        if (!sensorclockOK)
                        {
                            cumulus.LogDebugMessage("Within " + cumulus.FOReadAvoidPeriod + " seconds of sensor data change, skipping read");
                        }

                        if (!stationclockOK)
                        {
                            cumulus.LogDebugMessage("Within " + cumulus.FOReadAvoidPeriod + " seconds of station clock minute change, skipping read");
                        }

                        return;
                    }
                }
            }

            // get the block of memory containing the current data location

            if (cumulus.DataLogging)
            {
                cumulus.LogMessage("Reading first block");
            }
            ReadAddress(0, data);

            int addr = (data[31] * 256) + data[30];

            if (cumulus.DataLogging)
            {
                cumulus.LogMessage("First block read, addr = " + addr.ToString("X8"));
            }

            if (addr != prevaddr)
            {
                // location has changed, skip this read to give it chance to update
                //cumulus.LogMessage("Location changed, skipping");
                if (SynchroPhase == 2)
                {
                    cumulus.LogDebugMessage("Address changed");
                    cumulus.LogDebugMessage("addr=" + addr.ToString("X4") + "previous=" + prevaddr.ToString("X4"));
                    FOStationClockTime = DateTime.Now;
                    StopSynchronising();
                }
            }
            else
            {
                if (cumulus.DataLogging)
                {
                    cumulus.LogMessage("Reading data, addr = " + addr.ToString("X8"));
                }

                ReadAddress(addr, data);

                if (cumulus.DataLogging)
                {
                    cumulus.LogMessage("Data read - " + BitConverter.ToString(data));
                }

                DateTime now = DateTime.Now;

                if (Synchronising)
                {
                    if (SynchroPhase == 1)
                    {
                        // phase 1 - sensor clock
                        bool datachanged = false;
                        // ReadCounter determines whether we actually process the data (every 10 seconds)
                        ReadCounter++;
                        if (hadfirstsyncdata)
                        {
                            for (int i = 0; i < 16; i++)
                            {
                                if (prevdata[i] != data[i])
                                {
                                    datachanged = true;
                                }
                            }

                            if (datachanged)
                            {
                                FOSensorClockTime = DateTime.Now;
                                SynchroPhase      = 2;
                            }
                        }
                    }
                    else
                    {
                        // Phase 2 - station clock
                        ReadCounter++;
                    }
                }

                hadfirstsyncdata = true;
                for (int i = 0; i < 16; i++)
                {
                    prevdata[i] = data[i];
                }

                if ((!Synchronising) || ((ReadCounter % 20) == 0))
                {
                    LatestFOReading = addr.ToString("X4") + ":";
                    for (int i = 0; i < 16; i++)
                    {
                        LatestFOReading = LatestFOReading + " " + data[i].ToString("X2");
                    }

                    if (cumulus.DataLogging)
                    {
                        cumulus.LogMessage(LatestFOReading);
                    }

                    // Indoor Humidity ====================================================
                    int inhum = data[1];
                    if ((inhum > 100) && (inhum != 255))
                    {
                        // bad value
                        cumulus.LogMessage("Ignoring bad data: inhum = " + inhum);
                    }
                    else
                    {
                        // 255 is the overflow value, when RH gets below 10% - use 10%
                        if (inhum == 255)
                        {
                            inhum = 10;
                        }

                        if (inhum > 0)
                        {
                            DoIndoorHumidity(inhum);
                        }
                    }

                    // Indoor temperature ===============================================
                    double intemp = ((data[2]) + (data[3] & 0x7F) * 256) / 10.0f;
                    var    sign   = (byte)(data[3] & 0x80);
                    if (sign == 0x80)
                    {
                        intemp = -intemp;
                    }

                    if ((intemp > -50) && (intemp < 50))
                    {
                        DoIndoorTemp(ConvertTempCToUser(intemp));
                    }

                    // Pressure =========================================================
                    double pressure = (data[7] + (data[8] * 256)) / 10.0f + pressureOffset;

                    if ((pressure < cumulus.EWminpressureMB) || (pressure > cumulus.EWmaxpressureMB))
                    {
                        // bad value
                        cumulus.LogMessage("Ignoring bad data: pressure = " + pressure.ToString());
                        cumulus.LogMessage("                   offset = " + EWpressureoffset.ToString());
                    }
                    else
                    {
                        if ((previouspress == 9999) || (Math.Abs(pressure - previouspress) < cumulus.EWpressurediff))
                        {
                            previouspress = pressure;

                            DoPressure(ConvertPressMBToUser(pressure), now);
                            // Get station pressure in hPa by subtracting offset and calibrating
                            // EWpressure offset is difference between rel and abs in hPa
                            // PressOffset is user calibration in user units.
                            pressure        = pressure - pressureOffset + PressureHPa(cumulus.PressOffset);
                            StationPressure = ConvertPressMBToUser(pressure);
                        }
                        else
                        {
                            LogSpikeRemoval("Pressure difference greater than specified; reading ignored");
                            LogSpikeRemoval("Old value = " + previouspress.ToString("F1") + " New value = " + pressure.ToString("F1") + " EWpressurediff = " +
                                            cumulus.EWpressurediff.ToString("F1"));
                        }

                        UpdatePressureTrendString();
                        UpdateStatusPanel(now);
                        DoForecast("", false);
                    }
                    var status = data[15];
                    if ((status & 0x40) != 0)
                    {
                        SensorContactLost = true;
                        cumulus.LogMessage("Sensor contact lost; ignoring outdoor data");
                    }
                    else
                    {
                        SensorContactLost = false;
                        // Outdoor Humidity ===================================================
                        int outhum = data[4];
                        if ((outhum > 100) && (outhum != 255))
                        {
                            // bad value
                            cumulus.LogMessage("Ignoring bad data: outhum = " + outhum);
                        }
                        else
                        {
                            // 255 is the overflow value, when RH gets below 10% - use 10%
                            if (outhum == 255)
                            {
                                outhum = 10;
                            }

                            if (outhum > 0)
                            {
                                if ((previoushum == 999) || (Math.Abs(outhum - previoushum) < cumulus.EWhumiditydiff))
                                {
                                    previoushum = outhum;
                                    DoOutdoorHumidity(outhum, now);
                                }
                                else
                                {
                                    LogSpikeRemoval("Humidity difference greater than specified; reading ignored");
                                    LogSpikeRemoval("Old value = " + previoushum + " New value = " + outhum + " EWhumiditydiff = " + cumulus.EWhumiditydiff.ToString("F1"));
                                }
                            }
                        }

                        // Wind =============================================================
                        double gust      = (data[10] + ((data[11] & 0xF0) * 16)) / 10.0f;
                        double windspeed = (data[9] + ((data[11] & 0x0F) * 256)) / 10.0f;
                        var    winddir   = (int)(data[12] * 22.5f);

                        if ((gust > 60) || (gust < 0))
                        {
                            // bad value
                            cumulus.LogMessage("Ignoring bad data: gust = " + gust.ToString());
                        }
                        else if ((windspeed > 60) || (windspeed < 0))
                        {
                            // bad value
                            cumulus.LogMessage("Ignoring bad data: speed = " + gust.ToString());
                        }
                        else
                        {
                            if (((previousgust == 999) || (Math.Abs(gust - previousgust) < cumulus.EWgustdiff)) &&
                                ((previouswind == 999) || (Math.Abs(windspeed - previouswind) < cumulus.EWwinddiff)))
                            {
                                previousgust = gust;
                                previouswind = windspeed;
                                DoWind(ConvertWindMSToUser(gust), winddir, ConvertWindMSToUser(windspeed), now);
                            }
                            else
                            {
                                LogSpikeRemoval("Wind or gust difference greater than specified; reading ignored");
                                LogSpikeRemoval("Gust: Old value = " + previousgust.ToString("F1") + " New value = " + gust.ToString("F1") + " EWgustdiff = " +
                                                cumulus.EWgustdiff.ToString("F1"));
                                LogSpikeRemoval("Wind: Old value = " + previouswind.ToString("F1") + " New value = " + windspeed.ToString("F1") + " EWwinddiff = " +
                                                cumulus.EWwinddiff.ToString("F1"));
                            }
                        }

                        // Outdoor Temperature ==============================================
                        double outtemp = ((data[5]) + (data[6] & 0x7F) * 256) / 10.0f;
                        sign = (byte)(data[6] & 0x80);
                        if (sign == 0x80)
                        {
                            outtemp = -outtemp;
                        }

                        if ((outtemp < -50) || (outtemp > 70))
                        {
                            // bad value
                            cumulus.LogMessage("Ignoring bad data: outtemp = " + outtemp);
                        }
                        else
                        {
                            if ((previoustemp == 999) || (Math.Abs(outtemp - previoustemp) < cumulus.EWtempdiff))
                            {
                                previoustemp = outtemp;

                                DoOutdoorTemp(ConvertTempCToUser(outtemp), now);

                                // Use current humidity for dewpoint
                                if (OutdoorHumidity > 0)
                                {
                                    OutdoorDewpoint = ConvertTempCToUser(MeteoLib.DewPoint(ConvertUserTempToC(OutdoorTemperature), OutdoorHumidity));

                                    CheckForDewpointHighLow(now);
                                }
                                ;

                                // calculate wind chill
                                if ((outtemp > -50) || (outtemp < 70))
                                {
                                    // The 'global average speed will have been determined by the call of DoWind
                                    // so use that in the wind chill calculation
                                    double avgspeedKPH = ConvertUserWindToKPH(WindAverage);

                                    // windinMPH = calibwind * 2.23693629;
                                    // calculate wind chill from calibrated C temp and calibrated win in KPH
                                    double val = MeteoLib.WindChill(ConvertUserTempToC(OutdoorTemperature), avgspeedKPH);

                                    DoWindChill(ConvertTempCToUser(val), now);
                                }

                                DoApparentTemp(now);
                            }
                            else
                            {
                                LogSpikeRemoval("Temp difference greater than specified; reading ignored");
                                LogSpikeRemoval("Old value = " + previoustemp + " New value = " + outtemp + " EWtempdiff = " + cumulus.EWtempdiff);
                            }
                        }

                        // Rain ============================================================
                        int raintot = data[13] + (data[14] * 256);
                        if (prevraintotal == -1)
                        {
                            // first reading
                            prevraintotal = raintot;
                            cumulus.LogMessage("Rain total count from station = " + raintot);
                        }

                        int raindiff = Math.Abs(raintot - prevraintotal);

                        if (raindiff > cumulus.EWMaxRainTipDiff)
                        {
                            cumulus.LogMessage("Warning: large difference in rain gauge tip count: " + raindiff);

                            ignoreraincount++;

                            if (ignoreraincount == 6)
                            {
                                cumulus.LogMessage("Six consecutive readings; accepting value. Adjusting start of day figure to compensate");
                                raindaystart = raindaystart + (raindiff * 0.3);
                                // adjust current rain total counter
                                Raincounter = Raincounter + (raindiff * 0.3);
                                cumulus.LogMessage("Setting raindaystart to " + raindaystart);
                                ignoreraincount = 0;
                            }
                            else
                            {
                                cumulus.LogMessage("Ignoring reading " + ignoreraincount);
                            }
                        }
                        else
                        {
                            ignoreraincount = 0;
                        }

                        if (ignoreraincount == 0)
                        {
                            DoRain(ConvertRainMMToUser(raintot * 0.3), -1, now);
                            prevraintotal = raintot;
                        }

                        // Solar/UV
                        if (hasSolar)
                        {
                            LightValue = (data[16] + (data[17] * 256) + (data[18] * 65536)) / 10.0;

                            if (LightValue < 300000)
                            {
                                DoSolarRad((int)(LightValue * cumulus.LuxToWM2), now);
                            }

                            int UVreading = data[19];

                            if (UVreading != 255)
                            {
                                DoUV(UVreading, now);
                            }
                        }
                    }
                }
            }

            prevaddr = addr;
        }
Example #5
0
        private void ImetGetData()
        {
            const int TEMP1POS  = 1;
            const int TEMP2POS  = 2;
            const int RELHUMPOS = 3;
            const int PRESSPOS  = 4;
            const int WINDPOS   = 5;
            const int DIRPOS    = 6;
            const int SUNPOS    = 7;
            const int RAINPOS   = 8;
            //const int CHECKSUMPOS = 9;

            DateTime now = DateTime.Now;

            int h   = now.Hour;
            int min = now.Minute;

            if (min != previousminute)
            {
                previousminute = min;

                if (cumulus.SyncTime && (h == cumulus.ClockSettingHour) && (min == 0))
                {
                    // It's 0400, set the station clock
                    SetStationClock();
                }
            }

            comport.Write("RDLV" + sLineBreak);
            // read the response
            var response = getResponse("rdlv");

            if (ValidChecksum(response))
            {
                cumulus.LogDataMessage(response);
                // split the data
                var sl = new List <string>(Regex.Split(response, ","));

                // Parse data using decimal points rather than user's decimal separator
                NumberFormatInfo provider = new NumberFormatInfo();
                provider.NumberDecimalSeparator = ".";

                double temp1     = 0;
                double windspeed = 0;

                if (!string.IsNullOrEmpty(sl[TEMP1POS]))
                {
                    temp1 = Convert.ToDouble(sl[TEMP1POS], provider);
                    DoOutdoorTemp(ConvertTempCToUser(temp1), now);
                }

                if (!string.IsNullOrEmpty(sl[TEMP2POS]))
                {
                    double temp2 = Convert.ToDouble(sl[TEMP2POS], provider);
                    if (cumulus.LogExtraSensors)
                    {
                        // use second temp as Extra Temp 1
                        DoExtraTemp(ConvertTempCToUser(temp2), 1);
                    }
                    else
                    {
                        // use second temp as wet bulb
                        DoWetBulb(ConvertTempCToUser(temp2), now);
                    }
                }

                if (!string.IsNullOrEmpty(sl[RELHUMPOS]))
                {
                    double hum = Convert.ToDouble(sl[RELHUMPOS], provider);
                    DoOutdoorHumidity((int)hum, now);
                }

                if (!string.IsNullOrEmpty(sl[PRESSPOS]))
                {
                    double press = Convert.ToDouble(sl[PRESSPOS], provider);
                    DoPressure(ConvertPressMBToUser(press), now);
                }

                if (!string.IsNullOrEmpty(sl[DIRPOS]) && !string.IsNullOrEmpty(sl[WINDPOS]))
                {
                    int winddir = Convert.ToInt32(sl[DIRPOS], provider);
                    windspeed = Convert.ToDouble(sl[WINDPOS], provider);

                    DoWind(ConvertWindMSToUser(windspeed), winddir, ConvertWindMSToUser(windspeed), now);
                }
                if (!string.IsNullOrEmpty(sl[RAINPOS]))
                {
                    double raintotal = Convert.ToDouble(sl[RAINPOS], provider);
                    DoRain(ConvertRainMMToUser(raintotal), -1, now);
                }

                if (!string.IsNullOrEmpty(sl[SUNPOS]))
                {
                    double sunhours = Convert.ToDouble(sl[SUNPOS], provider);
                    DoSunHours(sunhours, now);
                }

                if (!string.IsNullOrEmpty(sl[TEMP1POS]))
                {
                    double windchill = MeteoLib.WindChill(temp1, windspeed * 3.6);
                    DoWindChill(windchill, now);
                }

                DoApparentTemp(now);

                DoForecast("", false);

                UpdatePressureTrendString();

                UpdateStatusPanel(now);
            }
            else
            {
                cumulus.LogMessage("Invalid checksum:");
                cumulus.LogMessage(response);
            }

            if (cumulus.ImetUpdateLogPointer)
            {
                // Keep the log pointer current, to avoid large numbers of logs
                // being downloaded at next startup
                ProgressLogs();
            }
        }
Example #6
0
        private void processHistoryData()
        {
            int totalentries = datalist.Count;

            cumulus.LogMessage("Processing history data, number of entries = " + totalentries);

            int rollHour = Math.Abs(cumulus.GetHourInc());

            int luhour = cumulus.LastUpdateTime.Hour;

            bool rolloverdone = luhour == rollHour;

            bool midnightraindone = luhour == 0;

            while (datalist.Count > 0)
            {
                HistoryData historydata = datalist[datalist.Count - 1];

                DateTime timestamp = historydata.timestamp;

                cumulus.LogMessage("Processing data for " + timestamp);

                int h = timestamp.Hour;

                //  if outside rollover hour, rollover yet to be done
                if (h != rollHour)
                {
                    rolloverdone = false;
                }

                // In rollover hour and rollover not yet done
                if ((h == rollHour) && !rolloverdone)
                {
                    // do rollover
                    cumulus.LogMessage("Day rollover " + timestamp.ToShortTimeString());
                    DayReset(timestamp);

                    rolloverdone = true;
                }

                // Not in midnight hour, midnight rain yet to be done
                if (h != 0)
                {
                    midnightraindone = false;
                }

                // In midnight hour and midnight rain (and sun) not yet done
                if ((h == 0) && !midnightraindone)
                {
                    ResetMidnightRain(timestamp);
                    ResetSunshineHours();
                    midnightraindone = true;
                }

                // Indoor Humidity ======================================================
                if ((historydata.inHum > 100) && (historydata.inHum != 255))
                {
                    cumulus.LogMessage("Ignoring bad data: inhum = " + historydata.inHum);
                }
                else if ((historydata.inHum > 0) && (historydata.inHum != 255))
                {
                    // 255 is the overflow value, when RH gets below 10% - ignore
                    DoIndoorHumidity(historydata.inHum);
                }

                // Indoor Temperature ===================================================
                if ((historydata.inTemp > -50) && (historydata.inTemp < 50))
                {
                    DoIndoorTemp(ConvertTempCToUser(historydata.inTemp));
                }

                // Pressure =============================================================

                if ((historydata.pressure < cumulus.EWminpressureMB) || (historydata.pressure > cumulus.EWmaxpressureMB))
                {
                    cumulus.LogMessage("Ignoring bad data: pressure = " + historydata.pressure);
                    cumulus.LogMessage("                   offset = " + pressureOffset);
                }
                else
                {
                    DoPressure(ConvertPressMBToUser(historydata.pressure), timestamp);
                }

                if (historydata.SensorContactLost)
                {
                    cumulus.LogMessage("Sensor contact lost; ignoring outdoor data");
                }
                else
                {
                    // Outdoor Humidity =====================================================
                    if ((historydata.outHum > 100) && (historydata.outHum != 255))
                    {
                        cumulus.LogMessage("Ignoring bad data: outhum = " + historydata.outHum);
                    }
                    else if ((historydata.outHum > 0) && (historydata.outHum != 255))
                    {
                        // 255 is the overflow value, when RH gets below 10% - ignore
                        DoOutdoorHumidity(historydata.outHum, timestamp);
                    }

                    // Wind =================================================================
                    if ((historydata.windGust > 60) || (historydata.windGust < 0))
                    {
                        cumulus.LogMessage("Ignoring bad data: gust = " + historydata.windGust);
                    }
                    else if ((historydata.windSpeed > 60) || (historydata.windSpeed < 0))
                    {
                        cumulus.LogMessage("Ignoring bad data: speed = " + historydata.windSpeed);
                    }
                    {
                        DoWind(ConvertWindMSToUser(historydata.windGust), historydata.windBearing, ConvertWindMSToUser(historydata.windSpeed), timestamp);
                    }

                    // Outdoor Temperature ==================================================
                    if ((historydata.outTemp < -50) || (historydata.outTemp > 70))
                    {
                        cumulus.LogMessage("Ignoring bad data: outtemp = " + historydata.outTemp);
                    }
                    else
                    {
                        DoOutdoorTemp(ConvertTempCToUser(historydata.outTemp), timestamp);
                        // add in 'archivePeriod' minutes worth of temperature to the temp samples
                        tempsamplestoday = tempsamplestoday + historydata.interval;
                        TempTotalToday   = TempTotalToday + (OutdoorTemperature * historydata.interval);
                    }

                    // update chill hours
                    if (OutdoorTemperature < cumulus.ChillHourThreshold)
                    {
                        // add 1 minute to chill hours
                        ChillHours = ChillHours + (historydata.interval / 60);
                    }

                    int raindiff;
                    if (prevraintotal == -1)
                    {
                        raindiff = 0;
                    }
                    else
                    {
                        raindiff = historydata.rainCounter - prevraintotal;
                    }

                    // record time of last rain tip, to use in
                    // normal running rain rate calc NB rain rate calc not currently used
                    if (raindiff > 0)
                    {
                        lastraintip = timestamp;

                        raininlasttip = raindiff;
                    }
                    else
                    {
                        lastraintip = DateTime.MinValue;

                        raininlasttip = 0;
                    }

                    double rainrate;

                    if (raindiff > 100)
                    {
                        cumulus.LogMessage("Warning: large increase in rain gauge tip count: " + raindiff);
                        rainrate = 0;
                    }
                    else
                    {
                        if (historydata.interval > 0)
                        {
                            rainrate = ConvertRainMMToUser((raindiff * 0.3) * (60.0 / historydata.interval));
                        }
                        else
                        {
                            rainrate = 0;
                        }
                    }

                    DoRain(ConvertRainMMToUser(historydata.rainCounter * 0.3), rainrate, timestamp);

                    prevraintotal = historydata.rainCounter;

                    OutdoorDewpoint = ConvertTempCToUser(MeteoLib.DewPoint(ConvertUserTempToC(OutdoorTemperature), OutdoorHumidity));

                    CheckForDewpointHighLow(timestamp);


                    // calculate wind chill

                    if (ConvertUserWindToMS(WindAverage) < 1.5)
                    {
                        DoWindChill(OutdoorTemperature, timestamp);
                    }
                    else
                    {
                        // calculate wind chill from calibrated C temp and calibrated win in KPH
                        DoWindChill(ConvertTempCToUser(MeteoLib.WindChill(ConvertUserTempToC(OutdoorTemperature), ConvertUserWindToKPH(WindAverage))), timestamp);
                    }

                    DoApparentTemp(timestamp);

                    if (hasSolar)
                    {
                        if (historydata.uvVal == 255)
                        {
                            // ignore
                        }
                        else if (historydata.uvVal < 0)
                        {
                            DoUV(0, timestamp);
                        }
                        else if (historydata.uvVal > 16)
                        {
                            DoUV(16, timestamp);
                        }
                        else
                        {
                            DoUV(historydata.uvVal, timestamp);
                        }

                        if ((historydata.solarVal >= 0) && (historydata.solarVal <= 300000))
                        {
                            DoSolarRad((int)Math.Floor(historydata.solarVal * cumulus.LuxToWM2), timestamp);

                            // add in archive period worth of sunshine, if sunny
                            if ((SolarRad > CurrentSolarMax * cumulus.SunThreshold / 100) && (SolarRad >= cumulus.SolarMinimum))
                            {
                                SunshineHours = SunshineHours + (historydata.interval / 60.0);
                            }

                            LightValue = historydata.solarVal;
                        }
                    }
                }
                // add in 'following interval' minutes worth of wind speed to windrun
                cumulus.LogMessage("Windrun: " + WindAverage.ToString(cumulus.WindFormat) + cumulus.WindUnitText + " for " + historydata.followinginterval + " minutes = " +
                                   (WindAverage * WindRunHourMult[cumulus.WindUnit] * historydata.followinginterval / 60.0).ToString(cumulus.WindRunFormat) + cumulus.WindRunUnitText);

                WindRunToday += (WindAverage * WindRunHourMult[cumulus.WindUnit] * historydata.followinginterval / 60.0);

                // update heating/cooling degree days
                UpdateDegreeDays(historydata.interval);

                // update dominant wind bearing
                CalculateDominantWindBearing(Bearing, WindAverage, historydata.interval);

                CheckForWindrunHighLow(timestamp);


                bw.ReportProgress((totalentries - datalist.Count) * 100 / totalentries, "processing");

                //UpdateDatabase(timestamp.ToUniversalTime(), historydata.interval, false);

                cumulus.DoLogFile(timestamp, false);
                if (cumulus.LogExtraSensors)
                {
                    cumulus.DoExtraLogFile(timestamp);
                }

                AddLastHourDataEntry(timestamp, Raincounter, OutdoorTemperature);
                AddGraphDataEntry(timestamp, Raincounter, RainToday, RainRate, OutdoorTemperature, OutdoorDewpoint, ApparentTemperature, WindChill, HeatIndex,
                                  IndoorTemperature, Pressure, WindAverage, RecentMaxGust, AvgBearing, Bearing, OutdoorHumidity, IndoorHumidity, SolarRad, CurrentSolarMax, UV);
                AddLast3HourDataEntry(timestamp, Pressure, OutdoorTemperature);
                AddRecentDataEntry(timestamp, WindAverage, RecentMaxGust, WindLatest, Bearing, AvgBearing, OutdoorTemperature, WindChill, OutdoorDewpoint, HeatIndex,
                                   OutdoorHumidity, Pressure, RainToday, SolarRad, UV, Raincounter);
                RemoveOldLHData(timestamp);
                RemoveOldL3HData(timestamp);
                RemoveOldGraphData(timestamp);
                DoTrendValues(timestamp);
                UpdatePressureTrendString();
                UpdateStatusPanel(timestamp);
                cumulus.AddToWebServiceLists(timestamp);
                datalist.RemoveAt(datalist.Count - 1);
            }
            cumulus.LogMessage("End processing history data");
        }
Example #7
0
        private void ProcessHistoryData(List <Observation> datalist)
        {
            var totalentries = datalist.Count;

            cumulus.LogMessage("Processing history data, number of entries = " + totalentries);
            cumulus.LogConsoleMessage(
                $"Processing history data for {totalentries} records. {DateTime.Now.ToLongTimeString()}");

            var rollHour         = Math.Abs(cumulus.GetHourInc());
            var luhour           = cumulus.LastUpdateTime.Hour;
            var rolloverdone     = luhour == rollHour;
            var midnightraindone = luhour == 0;

            var ticks = Environment.TickCount;

            foreach (var historydata in datalist)
            {
                var timestamp = historydata.Timestamp;

                cumulus.LogMessage("Processing data for " + timestamp);

                var h = timestamp.Hour;

                //  if outside rollover hour, rollover yet to be done
                if (h != rollHour)
                {
                    rolloverdone = false;
                }

                // In rollover hour and rollover not yet done
                if (h == rollHour && !rolloverdone)
                {
                    // do rollover
                    cumulus.LogMessage("Day rollover " + timestamp.ToShortTimeString());
                    DayReset(timestamp);

                    rolloverdone = true;
                }

                // Not in midnight hour, midnight rain yet to be done
                if (h != 0)
                {
                    midnightraindone = false;
                }

                // In midnight hour and midnight rain (and sun) not yet done
                if (h == 0 && !midnightraindone)
                {
                    ResetMidnightRain(timestamp);
                    ResetSunshineHours();
                    midnightraindone = true;
                }

                // Pressure =============================================================
                var alt      = AltitudeM(cumulus.Altitude);
                var seaLevel = GetSeaLevelPressure(alt, (double)historydata.StationPressure, (double)historydata.Temperature);
                DoPressure(ConvertPressMBToUser(seaLevel), timestamp);

                // Outdoor Humidity =====================================================
                DoOutdoorHumidity((int)historydata.Humidity, timestamp);

                // Wind =================================================================
                DoWind(ConvertWindMSToUser((double)historydata.WindGust), historydata.WindDirection,
                       ConvertWindMSToUser((double)historydata.WindAverage), timestamp);

                // Outdoor Temperature ==================================================
                DoOutdoorTemp(ConvertTempCToUser((double)historydata.Temperature), timestamp);
                // add in 'archivePeriod' minutes worth of temperature to the temp samples
                tempsamplestoday += historydata.ReportInterval;
                TempTotalToday   += OutdoorTemperature * historydata.ReportInterval;

                // update chill hours
                if (OutdoorTemperature < cumulus.ChillHourThreshold)
                {
                    // add 1 minute to chill hours
                    ChillHours += historydata.ReportInterval / 60.0;
                }

                double rainrate = (double)(ConvertRainMMToUser((double)historydata.Precipitation) *
                                           (60d / historydata.ReportInterval));

                var newRain = Raincounter + ConvertRainMMToUser((double)historydata.Precipitation);
                cumulus.LogMessage(
                    $"TempestDoRainHist: New Precip: {historydata.Precipitation}, Type: {historydata.PrecipType}, Rate: {rainrate}, LocalDayRain: {historydata.LocalDayRain}, LocalRainChecked: {historydata.LocalRainChecked}, FinalRainChecked: {historydata.FinalRainChecked}");

                DoRain(newRain, rainrate, timestamp);
                cumulus.LogMessage(
                    $"TempestDoRainHist: Total Precip for Day: {Raincounter}");

                OutdoorDewpoint =
                    ConvertTempCToUser(MeteoLib.DewPoint(ConvertUserTempToC(OutdoorTemperature),
                                                         OutdoorHumidity));

                CheckForDewpointHighLow(timestamp);

                // calculate wind chill

                if (ConvertUserWindToMS(WindAverage) < 1.5)
                {
                    DoWindChill(OutdoorTemperature, timestamp);
                }
                else
                {
                    // calculate wind chill from calibrated C temp and calibrated win in KPH
                    DoWindChill(
                        ConvertTempCToUser(MeteoLib.WindChill(ConvertUserTempToC(OutdoorTemperature),
                                                              ConvertUserWindToKPH(WindAverage))), timestamp);
                }

                DoApparentTemp(timestamp);
                DoFeelsLike(timestamp);
                DoHumidex(timestamp);


                DoUV((double)historydata.UV, timestamp);

                DoSolarRad(historydata.SolarRadiation, timestamp);

                // add in archive period worth of sunshine, if sunny
                if (SolarRad > CurrentSolarMax * cumulus.SunThreshold / 100 &&
                    SolarRad >= cumulus.SolarMinimum)
                {
                    SunshineHours += historydata.ReportInterval / 60.0;
                }

                LightValue = historydata.Illuminance;


                // add in 'following interval' minutes worth of wind speed to windrun
                cumulus.LogMessage("Windrun: " + WindAverage.ToString(cumulus.WindFormat) + cumulus.Units.WindText + " for " + historydata.ReportInterval + " minutes = " +
                                   (WindAverage * WindRunHourMult[cumulus.Units.Wind] * historydata.ReportInterval / 60.0).ToString(cumulus.WindRunFormat) + cumulus.Units.WindRunText);

                WindRunToday += WindAverage * WindRunHourMult[cumulus.Units.Wind] * historydata.ReportInterval / 60.0;

                // update heating/cooling degree days
                UpdateDegreeDays(historydata.ReportInterval);

                // update dominant wind bearing
                CalculateDominantWindBearing(Bearing, WindAverage, historydata.ReportInterval);

                CheckForWindrunHighLow(timestamp);

                bw?.ReportProgress((totalentries - datalist.Count) * 100 / totalentries, "processing");

                //UpdateDatabase(timestamp.ToUniversalTime(), historydata.interval, false);

                cumulus.DoLogFile(timestamp, false);
                if (cumulus.StationOptions.LogExtraSensors)
                {
                    cumulus.DoExtraLogFile(timestamp);
                }

                //AddRecentDataEntry(timestamp, WindAverage, RecentMaxGust, WindLatest, Bearing, AvgBearing,
                //    OutdoorTemperature, WindChill, OutdoorDewpoint, HeatIndex,
                //    OutdoorHumidity, Pressure, RainToday, SolarRad, UV, Raincounter, FeelsLike, Humidex);

                AddRecentDataWithAq(timestamp, WindAverage, RecentMaxGust, WindLatest, Bearing, AvgBearing, OutdoorTemperature, WindChill, OutdoorDewpoint, HeatIndex,
                                    OutdoorHumidity, Pressure, RainToday, SolarRad, UV, Raincounter, FeelsLike, Humidex, ApparentTemperature, IndoorTemperature, IndoorHumidity, CurrentSolarMax, RainRate);

                DoTrendValues(timestamp);
                UpdatePressureTrendString();
                UpdateStatusPanel(timestamp);
                cumulus.AddToWebServiceLists(timestamp);
            }

            ticks = Environment.TickCount - ticks;
            var rate = ((double)totalentries / ticks) * 1000;

            cumulus.LogMessage($"End processing history data. Rate: {rate:f2}/second");
            cumulus.LogConsoleMessage($"Completed processing history data. {DateTime.Now.ToLongTimeString()}, Rate: {rate:f2}/second");
        }
Example #8
0
        private void WeatherPacketReceived(WeatherPacket wp)
        {
            DateTime ts;

            if (wp != null)
            {
                switch (wp.MsgType)
                {
                case WeatherPacket.MessageType.Observation:
                    ts = wp.Observation.Timestamp;
                    var userTemp = ConvertTempCToUser(Convert.ToDouble(wp.Observation.Temperature));

                    DoOutdoorTemp(userTemp, ts);
                    DoWind(ConvertWindMSToUser((double)wp.Observation.WindGust),
                           wp.Observation.WindDirection,
                           ConvertWindMSToUser((double)wp.Observation.WindAverage),
                           ts);

                    var alt      = AltitudeM(cumulus.Altitude);
                    var seaLevel = GetSeaLevelPressure(alt, (double)wp.Observation.StationPressure,
                                                       (double)wp.Observation.Temperature);
                    DoPressure(ConvertPressMBToUser(seaLevel), ts);
                    cumulus.LogMessage(
                        $"TempestPressure: Station:{wp.Observation.StationPressure} mb, Sea Level:{seaLevel} mb, Altitude:{alt}");

                    DoSolarRad(wp.Observation.SolarRadiation, ts);
                    DoUV((double)wp.Observation.UV, ts);
                    double rainrate = (double)(ConvertRainMMToUser((double)wp.Observation.Precipitation) *
                                               (60d / wp.Observation.ReportInterval));

                    var newRain = Raincounter + ConvertRainMMToUser((double)wp.Observation.Precipitation);
                    cumulus.LogMessage(
                        $"TempestDoRain: New Precip: {wp.Observation.Precipitation}, Type: {wp.Observation.PrecipType}, Rate: {rainrate}");

                    DoRain(newRain, rainrate, ts);
                    cumulus.LogMessage(
                        $"TempestDoRain: Total Precip for Day: {Raincounter}");

                    DoOutdoorHumidity((int)wp.Observation.Humidity, ts);

                    OutdoorDewpoint =
                        ConvertTempCToUser(MeteoLib.DewPoint(ConvertUserTempToC(OutdoorTemperature),
                                                             OutdoorHumidity));

                    CheckForDewpointHighLow(ts);

                    DoApparentTemp(ts);
                    DoFeelsLike(ts);
                    DoWindChill(userTemp, ts);
                    DoHumidex(ts);
                    DoPressTrend(null);
                    UpdateStatusPanel(ts);
                    UpdateMQTT();
                    DoForecast(string.Empty, false);

                    cumulus.BatteryLowAlarm.Triggered = wp.Observation.BatteryVoltage <= 2.355M;

                    break;

                case WeatherPacket.MessageType.RapidWind:
                    var rw = wp.RapidWind;
                    DoWind(ConvertWindMSToUser((double)rw.WindSpeed),
                           rw.WindDirection,
                           ConvertWindMSToUser((double)rw.WindSpeed),
                           rw.Timestamp);
                    UpdateStatusPanel(rw.Timestamp);

                    break;

                case WeatherPacket.MessageType.LightningStrike:
                    LightningTime     = wp.LightningStrike.Timestamp;
                    LightningDistance = ConvertKmtoUserUnits(wp.LightningStrike.Distance);
                    LightningStrikesToday++;
                    cumulus.LogMessage($"Lightning Detected: {wp.LightningStrike.Timestamp} - {wp.LightningStrike.Distance} km - {LightningStrikesToday} strikes today");
                    break;
                }
            }
        }
Example #9
0
        private int ws2300ReadHistoryRecord(int record, out int address, out double tempindoor, out double tempoutdoor, out double pressure, out int humindoor, out int humoutdoor,
                                            out double raincount, out double windspeed, out double winddir, out double dewpoint, out double windchill)
        {
            byte[] data    = new byte[20];
            byte[] command = new byte[25];

            int bytes = 10;
            int tempint;

            address = 0x6C6 + record * 19;
            cumulus.LogMessage("Reading history record " + record);
            if (ws2300ReadWithRetries(address, bytes, data, command) != bytes)
            {
                cumulus.LogMessage("Failed to read history record");
                tempindoor  = 0;
                tempoutdoor = 0;
                pressure    = 0;
                humindoor   = 0;
                humoutdoor  = 0;
                raincount   = 0;
                windspeed   = 0;
                winddir     = 0;
                dewpoint    = 0;
                windchill   = 0;
                return(-1000);
            }

            string msg = "History record read: ";

            for (int n = 0; n < bytes; n++)
            {
                msg += data[n].ToString("X2");
                msg += " ";
            }

            cumulus.LogMessage(msg);
            tempint = (data[4] << 12) + (data[3] << 4) + (data[2] >> 4);

            pressure = 1000 + (tempint % 10000) / 10.0;

            if (pressure >= 1502.2)
            {
                pressure = pressure - 1000;
            }

            pressure = ConvertPressMBToUser(pressure);

            humindoor = (int)((tempint - (tempint % 10000)) / 10000.0);

            humoutdoor = (data[5] >> 4) * 10 + (data[5] & 0xF);

            raincount = ConvertRainMMToUser(rainref + (((data[7] & 0xF) * 256 + data[6]) - raincountref) * 0.518);

            windspeed = (data[8] * 16 + (data[7] >> 4)) / 10.0;

            if (windspeed > 49.9)
            {
                // probably lost sensor contact
                windspeed = 0;
            }

            // need wind in kph for chill calc
            double windkmh = 3.6 * windspeed;

            tempint     = ((data[2] & 0xF) << 16) + (data[1] << 8) + data[0];
            tempindoor  = ConvertTempCToUser((tempint % 1000) / 10.0f - 30.0);
            tempoutdoor = (tempint - (tempint % 1000)) / 10000.0f - 30.0;

            windchill = ConvertTempCToUser(MeteoLib.WindChill(tempoutdoor, windkmh));
            dewpoint  = ConvertTempCToUser(MeteoLib.DewPoint(tempoutdoor, humoutdoor));

            tempoutdoor = ConvertTempCToUser(tempoutdoor);

            windspeed = ConvertWindMSToUser(windspeed);
            winddir   = (data[9] & 0xF) * 22.5;


            return((++record) % 0xAF);
        }
Example #10
0
        private void processHistoryData()
        {
            // history data is alread in correct units
            int totalentries = datalist.Count;
            int rollHour     = Math.Abs(cumulus.GetHourInc());
            int luhour       = cumulus.LastUpdateTime.Hour;

            bool rolloverdone = luhour == rollHour;

            bool midnightraindone = luhour == 0;

            double prevraintotal = -1;
            double raindiff, rainrate;

            double pressureoffset = ConvertPressMBToUser(ws2300PressureOffset());

            while (datalist.Count > 0)
            {
                historyData historydata = datalist[datalist.Count - 1];

                DateTime timestamp = historydata.timestamp;

                cumulus.LogMessage("Processing data for " + timestamp);
                // Check for rollover

                int h = timestamp.Hour;

                if (h != rollHour)
                {
                    rolloverdone = false;
                }

                if ((h == rollHour) && !rolloverdone)
                {
                    // do rollover
                    cumulus.LogMessage("WS2300: Day rollover " + timestamp);
                    DayReset(timestamp);

                    rolloverdone = true;
                }

                // handle rain since midnight reset
                if (h != 0)
                {
                    midnightraindone = false;
                }

                if ((h == 0) && !midnightraindone)
                {
                    ResetMidnightRain(timestamp);
                    ResetSunshineHours();
                    midnightraindone = true;
                }

                // Humidity ====================================================================
                if ((historydata.inHum > 0) && (historydata.inHum <= 100))
                {
                    DoIndoorHumidity(historydata.inHum);
                }
                if ((historydata.outHum > 0) && (historydata.outHum <= 100))
                {
                    DoOutdoorHumidity(historydata.outHum, timestamp);
                }

                // Wind ========================================================================
                if (historydata.windSpeed < cumulus.LCMaxWind)
                {
                    DoWind(historydata.windGust, historydata.windBearing, historydata.windSpeed, timestamp);
                }

                // Temperature ==================================================================
                if ((historydata.outTemp > -50) && (historydata.outTemp < 50))
                {
                    DoOutdoorTemp(historydata.outTemp, timestamp);

                    tempsamplestoday = tempsamplestoday + historydata.interval;
                    TempTotalToday   = TempTotalToday + (OutdoorTemperature * historydata.interval);

                    if (OutdoorTemperature < cumulus.ChillHourThreshold)
                    // add 1 minute to chill hours
                    {
                        ChillHours += (historydata.interval / 60.0);
                    }
                }

                if ((historydata.inTemp > -50) && (historydata.inTemp < 50))
                {
                    DoIndoorTemp(historydata.inTemp);
                }

                // Rain ==========================================================================
                if (prevraintotal < 0)
                {
                    raindiff = 0;
                }
                else
                {
                    raindiff = historydata.rainTotal - prevraintotal;
                }

                if (historydata.interval > 0)
                {
                    rainrate = (raindiff) * (60 / historydata.interval);
                }
                else
                {
                    rainrate = 0;
                }

                cumulus.LogMessage("WS2300: History rain total = " + historydata.rainTotal);

                DoRain(historydata.rainTotal, rainrate, timestamp);

                prevraintotal = historydata.rainTotal;

                // Dewpoint ====================================================================
                if (cumulus.CalculatedDP)
                {
                    double tempC = ConvertUserTempToC(OutdoorTemperature);
                    DoOutdoorDewpoint(ConvertTempCToUser(MeteoLib.DewPoint(tempC, OutdoorHumidity)), timestamp);
                    CheckForDewpointHighLow(timestamp);
                }
                else
                {
                    if (historydata.dewpoint < ConvertUserTempToC(60))
                    {
                        DoOutdoorDewpoint(CalibrateTemp(historydata.dewpoint), timestamp);
                    }
                }

                // Windchill ==================================================================
                if (cumulus.CalculatedWC)
                {
                    if (ConvertUserWindToMS(WindAverage) < 1.5)
                    {
                        DoWindChill(OutdoorTemperature, timestamp);
                    }
                    else
                    {
                        // calculate wind chill from calibrated C temp and calibrated win in KPH
                        DoWindChill(ConvertTempCToUser(MeteoLib.WindChill(ConvertUserTempToC(OutdoorTemperature), ConvertUserWindToKPH(WindAverage))), timestamp);
                    }
                }
                else
                {
                    if (historydata.windchill < ConvertTempCToUser(60))
                    {
                        DoWindChill(historydata.windchill, timestamp);
                    }
                }

                // Wind run ======================================================================
                cumulus.LogMessage("Windrun: " + WindAverage.ToString(cumulus.WindFormat) + cumulus.WindUnitText + " for " + historydata.interval + " minutes = " +
                                   (WindAverage * WindRunHourMult[cumulus.WindUnit] * historydata.interval / 60.0).ToString(cumulus.WindRunFormat) + cumulus.WindRunUnitText);

                WindRunToday += (WindAverage * WindRunHourMult[cumulus.WindUnit] * historydata.interval / 60.0);

                CheckForWindrunHighLow(timestamp);

                // Pressure ======================================================================
                double slpress = historydata.pressure + pressureoffset;

                if ((slpress > ConvertPressMBToUser(900)) && (slpress < ConvertPressMBToUser(1200)))
                {
                    DoPressure(slpress, timestamp);
                }

                // update heating/cooling degree days
                UpdateDegreeDays(historydata.interval);

                DoApparentTemp(timestamp);

                CalculateDominantWindBearing(Bearing, WindAverage, historydata.interval);

                bw.ReportProgress((totalentries - datalist.Count) * 100 / totalentries, "processing");

                //UpdateDatabase(timestamp.ToUniversalTime(), historydata.interval, false);

                cumulus.DoLogFile(timestamp, false);
                if (cumulus.LogExtraSensors)
                {
                    cumulus.DoExtraLogFile(timestamp);
                }

                AddLastHourDataEntry(timestamp, Raincounter, OutdoorTemperature);
                AddGraphDataEntry(timestamp, Raincounter, RainToday, RainRate, OutdoorTemperature, OutdoorDewpoint, ApparentTemperature, WindChill, HeatIndex, IndoorTemperature, Pressure, WindAverage, RecentMaxGust, AvgBearing, Bearing, OutdoorHumidity, IndoorHumidity, SolarRad, CurrentSolarMax, UV);
                AddLast3HourDataEntry(timestamp, Pressure, OutdoorTemperature);
                AddRecentDataEntry(timestamp, WindAverage, RecentMaxGust, WindLatest, Bearing, AvgBearing, OutdoorTemperature, WindChill, OutdoorDewpoint, HeatIndex, OutdoorHumidity,
                                   Pressure, RainToday, SolarRad, UV, Raincounter);
                RemoveOldLHData(timestamp);
                RemoveOldL3HData(timestamp);
                RemoveOldGraphData(timestamp);
                DoTrendValues(timestamp);
                UpdatePressureTrendString();
                UpdateStatusPanel(timestamp);
                cumulus.AddToWebServiceLists(timestamp);

                datalist.RemoveAt(datalist.Count - 1);
            }
        }