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); } } }
/// <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; }
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"); }
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"); }
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; } } }
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); }
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); } }