diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite index becfeafd..d78f042e 100644 Binary files a/.vs/slnx.sqlite and b/.vs/slnx.sqlite differ diff --git a/CumulusMX/Api.cs b/CumulusMX/Api.cs index 39bf6cb7..b8c074bf 100644 --- a/CumulusMX/Api.cs +++ b/CumulusMX/Api.cs @@ -134,6 +134,16 @@ public bool EditData() case "alltimerecordslogfile.json": return this.JsonResponse(dataEditor.GetAllTimeRecLogFile()); + + case "monthlyrecords.json": + return this.JsonResponse(dataEditor.GetMonthlyRecData()); + + case "monthlyrecordsdayfile.json": + return this.JsonResponse(dataEditor.GetMonthlyRecDayFile()); + + case "monthlyrecordslogfile.json": + return this.JsonResponse(dataEditor.GetMonthlyRecLogFile()); + } throw new KeyNotFoundException("Key Not Found: " + lastSegment); @@ -192,6 +202,10 @@ public bool EditData() case "alltime": return this.JsonResponse(dataEditor.EditAllTimeRecs(this)); + + case "monthly": + return this.JsonResponse(dataEditor.EditMonthlyRecs(this)); + } throw new KeyNotFoundException("Key Not Found: " + lastSegment); diff --git a/CumulusMX/Cumulus.cs b/CumulusMX/Cumulus.cs index 3df27823..1a350ea4 100644 --- a/CumulusMX/Cumulus.cs +++ b/CumulusMX/Cumulus.cs @@ -29,8 +29,8 @@ namespace CumulusMX public class Cumulus { ///////////////////////////////// - public string Version = "3.2.1"; - public string Build = "3057"; + public string Version = "3.2.2"; + public string Build = "3058"; ///////////////////////////////// private static string appGuid = "57190d2e-7e45-4efb-8c09-06a176cef3f3"; @@ -1291,9 +1291,9 @@ public Cumulus(int HTTPport, int WSport) LogMessage("RainDayThreshold=" + RainDayThreshold.ToString("F3")); LogMessage("Offsets and Multipliers:"); LogMessage("PO=" + PressOffset.ToString("F3") + " TO=" + TempOffset.ToString("F3") + " HO=" + HumOffset + " WDO=" + WindDirOffset + " ITO=" + - InTempoffset.ToString("F3") + "SO=" + SolarOffset.ToString("F3") + " UVO=" + UVOffset.ToString("F3")); + InTempoffset.ToString("F3") + " SO=" + SolarOffset.ToString("F3") + " UVO=" + UVOffset.ToString("F3")); LogMessage("PM=" + PressMult.ToString("F3") + " WSM=" + WindSpeedMult.ToString("F3") + " WGM=" + WindGustMult.ToString("F3") + " TM=" + TempMult.ToString("F3") + " TM2=" + TempMult2.ToString("F3") + - " HM=" + HumMult.ToString("F3") + " HM2=" + HumMult2.ToString("F3") + " RM=" + RainMult.ToString("F3") + "SM=" + SolarMult.ToString("F3") + " UVM=" + UVMult.ToString("F3")); + " HM=" + HumMult.ToString("F3") + " HM2=" + HumMult2.ToString("F3") + " RM=" + RainMult.ToString("F3") + " SM=" + SolarMult.ToString("F3") + " UVM=" + UVMult.ToString("F3")); LogMessage("Spike removal:"); LogMessage("TD=" + EWtempdiff.ToString("F3") + " GD=" + EWgustdiff.ToString("F3") + " WD=" + EWwinddiff.ToString("F3") + " HD=" + EWhumiditydiff.ToString("F3") + " PD=" + EWpressurediff.ToString("F3")); diff --git a/CumulusMX/CumulusMX.csproj b/CumulusMX/CumulusMX.csproj index 762e8e4a..0a1ac3cc 100644 --- a/CumulusMX/CumulusMX.csproj +++ b/CumulusMX/CumulusMX.csproj @@ -24,8 +24,8 @@ false false true - 3057 - 3.2.1.3057 + 3058 + 3.2.2.3058 false true true diff --git a/CumulusMX/DataEditor.cs b/CumulusMX/DataEditor.cs index 59643de2..1ef8b989 100644 --- a/CumulusMX/DataEditor.cs +++ b/CumulusMX/DataEditor.cs @@ -4,22 +4,18 @@ using System.Globalization; using System.IO; using System.Linq; -using System.Net; -using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; using Unosquare.Labs.EmbedIO; -using SQLite; namespace CumulusMX { internal class DataEditor { - private WeatherStation station; - private Cumulus cumulus; - private WebTags webtags; + private readonly WeatherStation station; + private readonly Cumulus cumulus; + private readonly WebTags webtags; - private List HourRainLog = new List(); + private readonly List hourRainLog = new List(); internal DataEditor(Cumulus cumulus, WeatherStation station, WebTags webtags) { @@ -31,7 +27,7 @@ internal DataEditor(Cumulus cumulus, WeatherStation station, WebTags webtags) //internal string EditRainToday(HttpListenerContext context) internal string EditRainToday(IHttpContext context) { - var InvC = new CultureInfo(""); + var invC = new CultureInfo(""); var request = context.Request; string text; using (var reader = new StreamReader(request.InputStream, request.ContentEncoding)) @@ -39,15 +35,14 @@ internal string EditRainToday(IHttpContext context) text = reader.ReadToEnd(); } - string[] kvPair = text.Split('='); - string key = kvPair[0]; - string raintodaystring = kvPair[1]; + var kvPair = text.Split('='); + var raintodaystring = kvPair[1]; - if (!String.IsNullOrEmpty(raintodaystring)) + if (!string.IsNullOrEmpty(raintodaystring)) { try { - double raintoday = Double.Parse(raintodaystring, CultureInfo.InvariantCulture); + var raintoday = double.Parse(raintodaystring, CultureInfo.InvariantCulture); cumulus.LogMessage("Before rain today edit, raintoday=" + station.RainToday.ToString(cumulus.RainFormat) + " Raindaystart=" + station.raindaystart.ToString(cumulus.RainFormat)); station.RainToday = raintoday; station.raindaystart = station.Raincounter - (station.RainToday / cumulus.RainMult); @@ -59,22 +54,22 @@ internal string EditRainToday(IHttpContext context) } } - var json = "{\"raintoday\":\"" + station.RainToday.ToString(cumulus.RainFormat, InvC) + - "\",\"raincounter\":\"" + station.Raincounter.ToString(cumulus.RainFormat, InvC) + - "\",\"startofdayrain\":\"" + station.raindaystart.ToString(cumulus.RainFormat, InvC) + - "\",\"rainmult\":\"" + cumulus.RainMult.ToString("F3", InvC) + "\"}"; + var json = "{\"raintoday\":\"" + station.RainToday.ToString(cumulus.RainFormat, invC) + + "\",\"raincounter\":\"" + station.Raincounter.ToString(cumulus.RainFormat, invC) + + "\",\"startofdayrain\":\"" + station.raindaystart.ToString(cumulus.RainFormat, invC) + + "\",\"rainmult\":\"" + cumulus.RainMult.ToString("F3", invC) + "\"}"; return json; } internal string GetRainTodayEditData() { - var InvC = new CultureInfo(""); - string step = (cumulus.RainDPlaces == 1 ? "0.1" : "0.01"); - var json = "{\"raintoday\":\"" + station.RainToday.ToString(cumulus.RainFormat, InvC) + - "\",\"raincounter\":\"" + station.Raincounter.ToString(cumulus.RainFormat, InvC) + - "\",\"startofdayrain\":\"" + station.raindaystart.ToString(cumulus.RainFormat, InvC) + - "\",\"rainmult\":\"" + cumulus.RainMult.ToString("F3", InvC) + + var invC = new CultureInfo(""); + var step = (cumulus.RainDPlaces == 1 ? "0.1" : "0.01"); + var json = "{\"raintoday\":\"" + station.RainToday.ToString(cumulus.RainFormat, invC) + + "\",\"raincounter\":\"" + station.Raincounter.ToString(cumulus.RainFormat, invC) + + "\",\"startofdayrain\":\"" + station.raindaystart.ToString(cumulus.RainFormat, invC) + + "\",\"rainmult\":\"" + cumulus.RainMult.ToString("F3", invC) + "\",\"step\":\"" + step + "\"}"; return json; @@ -136,9 +131,8 @@ internal string DeleteDiary(IHttpContext context) internal string GetAllTimeRecData() { - var timeStampFormat = "dd/MM/yy HH:mm"; - var dateStampFormat = "dd/MM/yy"; - var InvC = new CultureInfo(""); + const string timeStampFormat = "dd/MM/yy HH:mm"; + const string dateStampFormat = "dd/MM/yy"; // Records - Temperature values var json = "{\"highTempVal\":\"" + station.alltimerecarray[WeatherStation.AT_hightemp].value.ToString(cumulus.TempFormat) + "\","; json += "\"lowTempVal\":\"" + station.alltimerecarray[WeatherStation.AT_lowtemp].value.ToString(cumulus.TempFormat) + "\","; @@ -205,69 +199,68 @@ internal string GetAllTimeRecData() internal string GetAllTimeRecDayFile() { - var timeStampFormat = "dd/MM/yy HH:mm"; - var dateStampFormat = "dd/MM/yy"; - - int linenum = 0; - string LogFile = cumulus.Datapath + cumulus.GetLogFileName(cumulus.LastUpdateTime); - double highTempVal = -999; - double lowTempVal = 999; - double highDewPtVal = -999; - double lowDewPtVal = 999; - double highAppTempVal = -999; - double lowAppTempVal = 999; - double lowWindChillVal = 999; - double highHeatIndVal = -999; - double highMinTempVal = -999; - double lowMaxTempVal = 999; - double highTempRangeVal = -999; - double lowTempRangeVal = 999; - double highHumVal = -999; - double lowHumVal = 999; - double highBaroVal = -999; - double lowBaroVal = 99999; - double highGustVal = -999; - double highWindVal = -999; - double highWindRunVal = -999; - double highRainRateVal = -999; - double highRainHourVal = -999; - double highRainDayVal = -999; - double highRainMonthVal = -999; - int dryPeriodVal = 0; - int wetPeriodVal = 0; - DateTime highTempTime = new DateTime(1900, 01, 01); - DateTime lowTempTime = highTempTime; - DateTime highDewPtTime = highTempTime; - DateTime lowDewPtTime = highTempTime; - DateTime highAppTempTime = highTempTime; - DateTime lowAppTempTime = highTempTime; - DateTime lowWindChillTime = highTempTime; - DateTime highHeatIndTime = highTempTime; - DateTime highMinTempTime = highTempTime; - DateTime lowMaxTempTime = highTempTime; - DateTime highTempRangeTime = highTempTime; - DateTime lowTempRangeTime = highTempTime; - DateTime highHumTime = highTempTime; - DateTime lowHumTime = highTempTime; - DateTime highBaroTime = highTempTime; - DateTime lowBaroTime = highTempTime; - DateTime highGustTime = highTempTime; - DateTime highWindTime = highTempTime; - DateTime highWindRunTime = highTempTime; - DateTime highRainRateTime = highTempTime; - DateTime highRainHourTime = highTempTime; - DateTime highRainDayTime = highTempTime; - DateTime highRainMonthTime = highTempTime; - DateTime dryPeriodTime = highTempTime; - DateTime wetPeriodTime = highTempTime; - - DateTime thisDate = highTempTime; - double rainThisMonth = 0; - int currentDryPeriod = 0; - int currentWetPeriod = 0; - bool isDryNow = false; - DateTime thisDateDry = highTempTime; - DateTime thisDateWet = highTempTime; + const string timeStampFormat = "dd/MM/yy HH:mm"; + const string dateStampFormat = "dd/MM/yy"; + + var linenum = 0; + var highTempVal = -999.0; + var lowTempVal = 999.0; + var highDewPtVal = highTempVal; + var lowDewPtVal = lowTempVal; + var highAppTempVal = highTempVal; + var lowAppTempVal = lowTempVal; + var lowWindChillVal = lowTempVal; + var highHeatIndVal = highTempVal; + var highMinTempVal = highTempVal; + var lowMaxTempVal = lowTempVal; + var highTempRangeVal = highTempVal; + var lowTempRangeVal = lowTempVal; + var highHumVal = highTempVal; + var lowHumVal = lowTempVal; + var highBaroVal = highTempVal; + var lowBaroVal = 99999.0; + var highGustVal = highTempVal; + var highWindVal = highTempVal; + var highWindRunVal = highTempVal; + var highRainRateVal = highTempVal; + var highRainHourVal = highTempVal; + var highRainDayVal = highTempVal; + var highRainMonthVal = highTempVal; + var dryPeriodVal = 0; + var wetPeriodVal = 0; + var highTempTime = new DateTime(1900, 01, 01); + var lowTempTime = highTempTime; + var highDewPtTime = highTempTime; + var lowDewPtTime = highTempTime; + var highAppTempTime = highTempTime; + var lowAppTempTime = highTempTime; + var lowWindChillTime = highTempTime; + var highHeatIndTime = highTempTime; + var highMinTempTime = highTempTime; + var lowMaxTempTime = highTempTime; + var highTempRangeTime = highTempTime; + var lowTempRangeTime = highTempTime; + var highHumTime = highTempTime; + var lowHumTime = highTempTime; + var highBaroTime = highTempTime; + var lowBaroTime = highTempTime; + var highGustTime = highTempTime; + var highWindTime = highTempTime; + var highWindRunTime = highTempTime; + var highRainRateTime = highTempTime; + var highRainHourTime = highTempTime; + var highRainDayTime = highTempTime; + var highRainMonthTime = highTempTime; + var dryPeriodTime = highTempTime; + var wetPeriodTime = highTempTime; + + var thisDate = highTempTime; + var rainThisMonth = 0.0; + var currentDryPeriod = 0; + var currentWetPeriod = 0; + var isDryNow = false; + var thisDateDry = highTempTime; + var thisDateWet = highTempTime; var json = "{"; double rainThreshold = 0; @@ -281,167 +274,176 @@ internal string GetAllTimeRecDayFile() { try { - string[] dayfile = File.ReadAllLines(cumulus.DayFile); + var dayfile = File.ReadAllLines(cumulus.DayFile); - foreach (string line in dayfile) + foreach (var line in dayfile) { linenum++; var st = new List(Regex.Split(line, CultureInfo.CurrentCulture.TextInfo.ListSeparator)); - if (st.Count > 0) - { - string datestr = st[0]; - DateTime loggedDate = station.ddmmyyStrToDate(datestr); + if (st.Count <= 0) continue; - // This assumes the day file is in date order! - if (thisDate.Month != loggedDate.Month) - { - // monthly rain - if (rainThisMonth > highRainMonthVal) - { - highRainMonthVal = rainThisMonth; - highRainMonthTime = thisDate; - } - // reset the date and counter for a new month - thisDate = loggedDate; - rainThisMonth = 0; - } - // hi temp - if (Double.Parse(st[6]) > highTempVal) - { - highTempVal = Double.Parse(st[6]); - highTempTime = getDateTime(loggedDate, st[7]); - } - // lo temp - if (Double.Parse(st[4]) < lowTempVal) - { - lowTempVal = Double.Parse(st[4]); - lowTempTime = getDateTime(loggedDate, st[5]); - } - // hi dewpt - if (Double.Parse(st[35]) > highDewPtVal) - { - highDewPtVal = Double.Parse(st[35]); - highDewPtTime = getDateTime(loggedDate, st[36]); - } - // lo dewpt - if (Double.Parse(st[37]) < lowDewPtVal) - { - lowDewPtVal = Double.Parse(st[37]); - lowDewPtTime = getDateTime(loggedDate, st[38]); - } - // hi app temp - if (Double.Parse(st[27]) > highAppTempVal) - { - highAppTempVal = Double.Parse(st[27]); - highAppTempTime = getDateTime(loggedDate, st[28]); - } - // lo app temp - if (Double.Parse(st[29]) < lowAppTempVal) - { - lowAppTempVal = Double.Parse(st[29]); - lowAppTempTime = getDateTime(loggedDate, st[30]); - } - // lo wind chill - if (Double.Parse(st[33]) < lowWindChillVal) - { - lowWindChillVal = Double.Parse(st[33]); - lowWindChillTime = getDateTime(loggedDate, st[34]); - } - // hi heat index - if (Double.Parse(st[25]) > highHeatIndVal) - { - highHeatIndVal = Double.Parse(st[25]); - highHeatIndTime = getDateTime(loggedDate, st[26]); - } - // hi min temp - if (Double.Parse(st[4]) > highMinTempVal) - { - highMinTempVal = Double.Parse(st[4]); - highMinTempTime = loggedDate; - } - // lo max temp - if (Double.Parse(st[6]) < lowMaxTempVal) + var datestr = st[0]; + var loggedDate = station.ddmmyyStrToDate(datestr); + double valDbl, valDbl2; + + // This assumes the day file is in date order! + if (thisDate.Month != loggedDate.Month) + { + // monthly rain + if (rainThisMonth > highRainMonthVal) { - lowMaxTempVal = Double.Parse(st[6]); - lowMaxTempTime = loggedDate; + highRainMonthVal = rainThisMonth; + highRainMonthTime = thisDate; } + // reset the date and counter for a new month + thisDate = loggedDate; + rainThisMonth = 0; + } + // hi temp + if (double.TryParse(st[6], out valDbl) && valDbl > highTempVal) + { + highTempVal = valDbl; + highTempTime = GetDateTime(loggedDate, st[7]); + } + // lo temp + if (double.TryParse(st[4], out valDbl) && valDbl < lowTempVal) + { + lowTempVal = valDbl; + lowTempTime = GetDateTime(loggedDate, st[5]); + } + // hi dewpt + if (double.TryParse(st[35], out valDbl) && valDbl > highDewPtVal) + { + highDewPtVal = valDbl; + highDewPtTime = GetDateTime(loggedDate, st[36]); + } + // lo dewpt + if (double.TryParse(st[37], out valDbl) && valDbl < lowDewPtVal) + { + lowDewPtVal = valDbl; + lowDewPtTime = GetDateTime(loggedDate, st[38]); + } + // hi app temp + if (double.TryParse(st[27], out valDbl) && valDbl > highAppTempVal) + { + highAppTempVal = valDbl; + highAppTempTime = GetDateTime(loggedDate, st[28]); + } + // lo app temp + if (double.TryParse(st[29], out valDbl) && valDbl < lowAppTempVal) + { + lowAppTempVal = valDbl; + lowAppTempTime = GetDateTime(loggedDate, st[30]); + } + // lo wind chill + if (double.TryParse(st[33], out valDbl) && valDbl < lowWindChillVal) + { + lowWindChillVal = valDbl; + lowWindChillTime = GetDateTime(loggedDate, st[34]); + } + // hi heat index + if (double.TryParse(st[25], out valDbl) && valDbl > highHeatIndVal) + { + highHeatIndVal = valDbl; + highHeatIndTime = GetDateTime(loggedDate, st[26]); + } + // hi min temp + if (double.TryParse(st[4], out valDbl) && valDbl > highMinTempVal) + { + highMinTempVal = valDbl; + highMinTempTime = loggedDate; + } + // lo max temp + if (double.TryParse(st[6], out valDbl) && valDbl < lowMaxTempVal) + { + lowMaxTempVal = valDbl; + lowMaxTempTime = loggedDate; + } + // temp ranges + if (double.TryParse(st[6], out valDbl) && double.TryParse(st[4], out valDbl2)) + { // hi temp range - if (Double.Parse(st[6]) - Double.Parse(st[4]) > highTempRangeVal) + if ((valDbl - valDbl2) > highTempRangeVal) { - highTempRangeVal = Double.Parse(st[6]) - Double.Parse(st[4]); + highTempRangeVal = valDbl - valDbl2; highTempRangeTime = loggedDate; } // lo temp range - if (Double.Parse(st[6]) - Double.Parse(st[4]) < lowTempRangeVal) + if ((valDbl - valDbl2) < lowTempRangeVal) { - lowTempRangeVal = Double.Parse(st[6]) - Double.Parse(st[4]); + lowTempRangeVal = valDbl - valDbl2; lowTempRangeTime = loggedDate; } - // hi humidity - if (Double.Parse(st[21]) > highHumVal) - { - highHumVal = Double.Parse(st[21]); - highHumTime = getDateTime(loggedDate, st[22]); - } - // lo humidity - if (Double.Parse(st[19]) < lowHumVal) - { - lowHumVal = Double.Parse(st[19]); - lowHumTime = getDateTime(loggedDate, st[20]); - } - // hi baro - if (Double.Parse(st[10]) > highBaroVal) - { - highBaroVal = Double.Parse(st[10]); - highBaroTime = getDateTime(loggedDate, st[11]); - } - // lo baro - if (Double.Parse(st[8]) < lowBaroVal) - { - lowBaroVal = Double.Parse(st[8]); - lowBaroTime = getDateTime(loggedDate, st[9]); - } - // hi gust - if (Double.Parse(st[1]) > highGustVal) - { - highGustVal = Double.Parse(st[1]); - highGustTime = getDateTime(loggedDate, st[3]); - } - // hi wind - if (Double.Parse(st[17]) > highWindVal) - { - highWindVal = Double.Parse(st[17]); - highWindTime = getDateTime(loggedDate, st[18]); - } - // hi wind run - if (Double.Parse(st[16]) > highWindRunVal) - { - highWindRunVal = Double.Parse(st[16]); - highWindRunTime = loggedDate; - } - // hi rain rate - if (Double.Parse(st[12]) > highRainRateVal) - { - highRainRateVal = Double.Parse(st[12]); - highRainRateTime = getDateTime(loggedDate, st[13]); - } - // hi rain hour - if (Double.Parse(st[31]) > highRainHourVal) - { - highRainHourVal = Double.Parse(st[31]); - highRainHourTime = getDateTime(loggedDate, st[32]); - } + } + // hi humidity + if (double.TryParse(st[21], out valDbl) && valDbl > highHumVal) + { + highHumVal = valDbl; + highHumTime = GetDateTime(loggedDate, st[22]); + } + // lo humidity + if (double.TryParse(st[19], out valDbl) && valDbl < lowHumVal) + { + lowHumVal = valDbl; + lowHumTime = GetDateTime(loggedDate, st[20]); + } + // hi baro + if (double.TryParse(st[10], out valDbl) && valDbl > highBaroVal) + { + highBaroVal = valDbl; + highBaroTime = GetDateTime(loggedDate, st[11]); + } + // lo baro + if (double.TryParse(st[8], out valDbl) && valDbl < lowBaroVal) + { + lowBaroVal = valDbl; + lowBaroTime = GetDateTime(loggedDate, st[9]); + } + // hi gust + if (double.TryParse(st[1], out valDbl) && valDbl > highGustVal) + { + highGustVal = valDbl; + highGustTime = GetDateTime(loggedDate, st[3]); + } + // hi wind + if (double.TryParse(st[17], out valDbl) && valDbl > highWindVal) + { + highWindVal = valDbl; + highWindTime = GetDateTime(loggedDate, st[18]); + } + // hi wind run + if (double.TryParse(st[16], out valDbl) && valDbl > highWindRunVal) + { + highWindRunVal = valDbl; + highWindRunTime = loggedDate; + } + // hi rain rate + if (double.TryParse(st[12], out valDbl) && valDbl > highRainRateVal) + { + highRainRateVal = valDbl; + highRainRateTime = GetDateTime(loggedDate, st[13]); + } + // hi rain hour + if (double.TryParse(st[31], out valDbl) && valDbl > highRainHourVal) + { + highRainHourVal = valDbl; + highRainHourTime = GetDateTime(loggedDate, st[32]); + } + if (double.TryParse(st[14], out valDbl)) + { // hi rain day - if (Double.Parse(st[14]) > highRainDayVal) + if (valDbl > highRainDayVal) { - highRainDayVal = Double.Parse(st[14]); + highRainDayVal = valDbl; highRainDayTime = loggedDate; } + // monthly rain - rainThisMonth += Double.Parse(st[14]); + rainThisMonth += valDbl; + // dry/wet period - if (Double.Parse(st[14]) > rainThreshold) + if (valDbl > rainThreshold) { if (isDryNow) { @@ -533,9 +535,9 @@ internal string GetAllTimeRecDayFile() json += "\"longestWetPeriodValDayfile\":\"" + wetPeriodVal.ToString() + "\","; json += "\"longestWetPeriodTimeDayfile\":\"" + wetPeriodTime.ToString(dateStampFormat) + "\"}"; } - catch (Exception E) + catch (Exception e) { - cumulus.LogMessage("Error on line " + linenum + " of " + cumulus.DayFile + ": " + E.Message); + cumulus.LogMessage("Error on line " + linenum + " of " + cumulus.DayFile + ": " + e.Message); } } else @@ -552,8 +554,8 @@ internal string GetAllTimeRecDayFile() internal string GetAllTimeRecLogFile() { - var timeStampFormat = "dd/MM/yy HH:mm"; - var dateStampFormat = "dd/MM/yy"; + const string timeStampFormat = "dd/MM/yy HH:mm"; + const string dateStampFormat = "dd/MM/yy"; var json = "{"; var datefrom = DateTime.Parse(cumulus.RecordsBeganDate); @@ -562,92 +564,86 @@ internal string GetAllTimeRecLogFile() dateto = new DateTime(dateto.Year, dateto.Month, 1, 0, 0, 0); var filedate = datefrom; - string logFile = cumulus.GetLogFileName(filedate); - bool started = false; - bool finished = false; - var entrydate = datefrom; + var logFile = cumulus.GetLogFileName(filedate); + var started = false; + var finished = false; var lastentrydate = datefrom; - var metoDate = datefrom; var currentDay = datefrom; double dayHighTemp = -999; double dayLowTemp = 999; double dayWindRun = 0; - //double hourRain = 0; double dayRain = 0; - bool isDryNow = false; - int currentDryPeriod = 0; - int currentWetPeriod = 0; + var isDryNow = false; + var currentDryPeriod = 0; + var currentWetPeriod = 0; - double rainThreshold = 0; + var rainThreshold = 0.0; if (cumulus.RainDayThreshold > -1) rainThreshold = cumulus.RainDayThreshold; - double highTempVal = -999; - double lowTempVal = 999; - double highDewPtVal = -999; - double lowDewPtVal = 999; - double highAppTempVal = -999; - double lowAppTempVal = 999; - double lowWindChillVal = 999; - double highHeatIndVal = -999; - double highMinTempVal = -999; - double lowMaxTempVal = 999; - double highTempRangeVal = -999; - double lowTempRangeVal = 999; - double highHumVal = -999; - double lowHumVal = 999; - double highBaroVal = -999; - double lowBaroVal = 99999; - double highGustVal = -999; - double highWindVal = -999; - double highWindRunVal = -999; - double highRainRateVal = -999; - double highRainHourVal = -999; - double highRainDayVal = -999; - double highRainMonthVal = -999; - int dryPeriodVal = 0; - int wetPeriodVal = 0; - - DateTime highTempTime = new DateTime(1900, 01, 01); - DateTime lowTempTime = highTempTime; - DateTime highDewPtTime = highTempTime; - DateTime lowDewPtTime = highTempTime; - DateTime highAppTempTime = highTempTime; - DateTime lowAppTempTime = highTempTime; - DateTime lowWindChillTime = highTempTime; - DateTime highHeatIndTime = highTempTime; - DateTime highMinTempTime = highTempTime; - DateTime lowMaxTempTime = highTempTime; - DateTime highTempRangeTime = highTempTime; - DateTime lowTempRangeTime = highTempTime; - DateTime highHumTime = highTempTime; - DateTime lowHumTime = highTempTime; - DateTime highBaroTime = highTempTime; - DateTime lowBaroTime = highTempTime; - DateTime highGustTime = highTempTime; - DateTime highWindTime = highTempTime; - DateTime highWindRunTime = highTempTime; - DateTime highRainRateTime = highTempTime; - DateTime highRainHourTime = highTempTime; - DateTime highRainDayTime = highTempTime; - DateTime highRainMonthTime = highTempTime; - DateTime dryPeriodTime = highTempTime; - DateTime wetPeriodTime = highTempTime; - - DateTime thisDateDry = highTempTime; - DateTime thisDateWet = highTempTime; - - Double lastRainMidnight = 0; - Double rainMidnight = 0; - Double totalRainfall = 0; - - Double outsidetemp, dewpoint, speed, gust, rainrate, raintoday, pressure, chill, heat, apptemp; - int hum; + var highTempVal = -999.0; + var lowTempVal = 999.0; + var highDewPtVal = highTempVal; + var lowDewPtVal = lowTempVal; + var highAppTempVal = highTempVal; + var lowAppTempVal = lowTempVal; + var lowWindChillVal = lowTempVal; + var highHeatIndVal = highTempVal; + var highMinTempVal = highTempVal; + var lowMaxTempVal = lowTempVal; + var highTempRangeVal = highTempVal; + var lowTempRangeVal = lowTempVal; + var highHumVal = highTempVal; + var lowHumVal = lowTempVal; + var highBaroVal = highTempVal; + var lowBaroVal = 99999.0; + var highGustVal = highTempVal; + var highWindVal = highTempVal; + var highWindRunVal = highTempVal; + var highRainRateVal = highTempVal; + var highRainHourVal = highTempVal; + var highRainDayVal = highTempVal; + var highRainMonthVal = highTempVal; + var dryPeriodVal = 0; + var wetPeriodVal = 0; + + var highTempTime = new DateTime(1900, 01, 01); + var lowTempTime = highTempTime; + var highDewPtTime = highTempTime; + var lowDewPtTime = highTempTime; + var highAppTempTime = highTempTime; + var lowAppTempTime = highTempTime; + var lowWindChillTime = highTempTime; + var highHeatIndTime = highTempTime; + var highMinTempTime = highTempTime; + var lowMaxTempTime = highTempTime; + var highTempRangeTime = highTempTime; + var lowTempRangeTime = highTempTime; + var highHumTime = highTempTime; + var lowHumTime = highTempTime; + var highBaroTime = highTempTime; + var lowBaroTime = highTempTime; + var highGustTime = highTempTime; + var highWindTime = highTempTime; + var highWindRunTime = highTempTime; + var highRainRateTime = highTempTime; + var highRainHourTime = highTempTime; + var highRainDayTime = highTempTime; + var highRainMonthTime = highTempTime; + var dryPeriodTime = highTempTime; + var wetPeriodTime = highTempTime; + + var thisDateDry = highTempTime; + var thisDateWet = highTempTime; + + var totalRainfall = 0.0; var watch = System.Diagnostics.Stopwatch.StartNew(); + hourRainLog.Clear(); + while (!finished) { double monthlyRain = 0; @@ -655,21 +651,22 @@ internal string GetAllTimeRecLogFile() if (File.Exists(logFile)) { cumulus.LogDebugMessage($"GetAllTimeRecLogFile: Processing log file - {logFile}"); - int linenum = 0; + var linenum = 0; try { - string[] logfile = File.ReadAllLines(logFile); + var logfile = File.ReadAllLines(logFile); + double valDbl; - foreach (string line in logfile) + foreach (var line in logfile) { // process each record in the file linenum++; //var st = new List(Regex.Split(line, CultureInfo.CurrentCulture.TextInfo.ListSeparator)); // Regex is very expensive, let's assume the separator is always a single character var st = new List(line.Split((CultureInfo.CurrentCulture.TextInfo.ListSeparator)[0])); - entrydate = station.ddmmyyhhmmStrToDate(st[0], st[1]); + var entrydate = station.ddmmyyhhmmStrToDate(st[0], st[1]); // We need to work in meto dates not clock dates for day hi/lows - metoDate = entrydate.AddHours(cumulus.GetHourInc()); + var metoDate = entrydate.AddHours(cumulus.GetHourInc()); if (!started) { @@ -678,48 +675,45 @@ internal string GetAllTimeRecLogFile() started = true; } - outsidetemp = Convert.ToDouble(st[2]); - hum = Convert.ToInt32(st[3]); - dewpoint = Convert.ToDouble(st[4]); - speed = Convert.ToDouble(st[5]); - gust = Convert.ToDouble(st[6]); - rainrate = Convert.ToDouble(st[8]); - raintoday = Convert.ToDouble(st[9]); - pressure = Convert.ToDouble(st[10]); - if (st.Count >= 16) + var outsidetemp = double.Parse(st[2]); + var hum = int.Parse(st[3]); + var dewpoint = double.Parse(st[4]); + var speed = double.Parse(st[5]); + var gust = double.Parse(st[6]); + var rainrate = double.Parse(st[8]); + var raintoday = double.Parse(st[9]); + var pressure = double.Parse(st[10]); + if (st.Count > 15 && double.TryParse(st[15], out valDbl)) { - chill = Convert.ToDouble(st[15]); // low chill - if (chill < lowWindChillVal) + if (valDbl < lowWindChillVal) { - lowWindChillVal = chill; + lowWindChillVal = valDbl; lowWindChillTime = entrydate; } } - if (st.Count >= 17) + if (st.Count > 16 && double.TryParse(st[16], out valDbl)) { - heat = Convert.ToDouble(st[16]); // hi heat - if (heat > highHeatIndVal) + if (valDbl > highHeatIndVal) { - highHeatIndVal = heat; + highHeatIndVal = valDbl; highHeatIndTime = entrydate; } } - if (st.Count >= 22) + if (st.Count > 21 && double.TryParse(st[21], out valDbl)) { - apptemp = Convert.ToDouble(st[21]); // hi appt - if (apptemp > highAppTempVal) + if (valDbl > highAppTempVal) { - highAppTempVal = apptemp; + highAppTempVal = valDbl; highAppTempTime = entrydate; } // lo appt - if (apptemp < lowAppTempVal) + if (valDbl < lowAppTempVal) { - lowAppTempVal = apptemp; + lowAppTempVal = valDbl; lowAppTempTime = entrydate; } } @@ -897,10 +891,10 @@ internal string GetAllTimeRecLogFile() * need to track what the rainfall has been in the last rolling hour * across day rollovers where the count resets */ - AddLastHourRainEntry(entrydate, totalRainfall + raintoday); + AddLastHourRainEntry(entrydate, totalRainfall + dayRain); RemoveOldRainData(entrydate); - var rainThisHour = HourRainLog.Last().raincounter - HourRainLog.First().raincounter; + var rainThisHour = hourRainLog.Last().Raincounter - hourRainLog.First().Raincounter; if (rainThisHour > highRainHourVal) { highRainHourVal = rainThisHour; @@ -908,7 +902,7 @@ internal string GetAllTimeRecLogFile() } lastentrydate = entrydate; - lastRainMidnight = rainMidnight; + //lastRainMidnight = rainMidnight; } } catch (Exception e) @@ -992,9 +986,9 @@ internal string GetAllTimeRecLogFile() return json; } - private DateTime getDateTime(DateTime date, string time) + private static DateTime GetDateTime(DateTime date, string time) { - string[] tim = time.Split(CultureInfo.CurrentCulture.DateTimeFormat.TimeSeparator.ToCharArray()[0]); + var tim = time.Split(CultureInfo.CurrentCulture.DateTimeFormat.TimeSeparator.ToCharArray()[0]); return new DateTime(date.Year, date.Month, date.Day, int.Parse(tim[0]), int.Parse(tim[1]), 0); } @@ -1002,8 +996,7 @@ internal string EditAllTimeRecs(IHttpContext context) { var request = context.Request; string text; - int result; - string[] dt; + using (var reader = new StreamReader(request.InputStream, request.ContentEncoding)) { @@ -1013,161 +1006,162 @@ internal string EditAllTimeRecs(IHttpContext context) var newData = text.Split('&'); var field = newData[0].Split('=')[1]; var value = newData[1].Split('=')[1]; - result = 1; + var result = 1; try { + string[] dt; switch (field) { case "highTempVal": - station.SetAlltime(WeatherStation.AT_hightemp, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_hightemp].timestamp); + station.SetAlltime(WeatherStation.AT_hightemp, double.Parse(value), station.alltimerecarray[WeatherStation.AT_hightemp].timestamp); break; case "highTempTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_hightemp, station.alltimerecarray[WeatherStation.AT_hightemp].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "lowTempVal": - station.SetAlltime(WeatherStation.AT_lowtemp, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowtemp].timestamp); + station.SetAlltime(WeatherStation.AT_lowtemp, double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowtemp].timestamp); break; case "lowTempTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_lowtemp, station.alltimerecarray[WeatherStation.AT_lowtemp].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "highDewPointVal": - station.SetAlltime(WeatherStation.AT_highdewpoint, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_highdewpoint].timestamp); + station.SetAlltime(WeatherStation.AT_highdewpoint, double.Parse(value), station.alltimerecarray[WeatherStation.AT_highdewpoint].timestamp); break; case "highDewPointTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_highdewpoint, station.alltimerecarray[WeatherStation.AT_highdewpoint].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "lowDewPointVal": - station.SetAlltime(WeatherStation.AT_lowdewpoint, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowdewpoint].timestamp); + station.SetAlltime(WeatherStation.AT_lowdewpoint, double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowdewpoint].timestamp); break; case "lowDewPointTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_lowdewpoint, station.alltimerecarray[WeatherStation.AT_lowdewpoint].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "highApparentTempVal": - station.SetAlltime(WeatherStation.AT_highapptemp, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_highapptemp].timestamp); + station.SetAlltime(WeatherStation.AT_highapptemp, double.Parse(value), station.alltimerecarray[WeatherStation.AT_highapptemp].timestamp); break; case "highApparentTempTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_highapptemp, station.alltimerecarray[WeatherStation.AT_highapptemp].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "lowApparentTempVal": - station.SetAlltime(WeatherStation.AT_lowapptemp, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowapptemp].timestamp); + station.SetAlltime(WeatherStation.AT_lowapptemp, double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowapptemp].timestamp); break; case "lowApparentTempTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_lowapptemp, station.alltimerecarray[WeatherStation.AT_lowapptemp].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "lowWindChillVal": - station.SetAlltime(WeatherStation.AT_lowchill, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowchill].timestamp); + station.SetAlltime(WeatherStation.AT_lowchill, double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowchill].timestamp); break; case "lowWindChillTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_lowchill, station.alltimerecarray[WeatherStation.AT_lowchill].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "highHeatIndexVal": - station.SetAlltime(WeatherStation.AT_highheatindex, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_highheatindex].timestamp); + station.SetAlltime(WeatherStation.AT_highheatindex, double.Parse(value), station.alltimerecarray[WeatherStation.AT_highheatindex].timestamp); break; case "highHeatIndexTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_highheatindex, station.alltimerecarray[WeatherStation.AT_highheatindex].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "highMinTempVal": - station.SetAlltime(WeatherStation.AT_highmintemp, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_highmintemp].timestamp); + station.SetAlltime(WeatherStation.AT_highmintemp, double.Parse(value), station.alltimerecarray[WeatherStation.AT_highmintemp].timestamp); break; case "highMinTempTime": station.SetAlltime(WeatherStation.AT_highmintemp, station.alltimerecarray[WeatherStation.AT_highmintemp].value, station.ddmmyyStrToDate(value)); break; case "lowMaxTempVal": - station.SetAlltime(WeatherStation.AT_lowmaxtemp, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowmaxtemp].timestamp); + station.SetAlltime(WeatherStation.AT_lowmaxtemp, double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowmaxtemp].timestamp); break; case "lowMaxTempTime": station.SetAlltime(WeatherStation.AT_lowmaxtemp, station.alltimerecarray[WeatherStation.AT_lowmaxtemp].value, station.ddmmyyStrToDate(value)); break; case "highDailyTempRangeVal": - station.SetAlltime(WeatherStation.AT_highdailytemprange, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_highdailytemprange].timestamp); + station.SetAlltime(WeatherStation.AT_highdailytemprange, double.Parse(value), station.alltimerecarray[WeatherStation.AT_highdailytemprange].timestamp); break; case "highDailyTempRangeTime": station.SetAlltime(WeatherStation.AT_highdailytemprange, station.alltimerecarray[WeatherStation.AT_highdailytemprange].value, station.ddmmyyStrToDate(value)); break; case "lowDailyTempRangeVal": - station.SetAlltime(WeatherStation.AT_lowdailytemprange, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowdailytemprange].timestamp); + station.SetAlltime(WeatherStation.AT_lowdailytemprange, double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowdailytemprange].timestamp); break; case "lowDailyTempRangeTime": station.SetAlltime(WeatherStation.AT_lowdailytemprange, station.alltimerecarray[WeatherStation.AT_lowdailytemprange].value, station.ddmmyyStrToDate(value)); break; case "highHumidityVal": - station.SetAlltime(WeatherStation.AT_highhumidity, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_highhumidity].timestamp); + station.SetAlltime(WeatherStation.AT_highhumidity, double.Parse(value), station.alltimerecarray[WeatherStation.AT_highhumidity].timestamp); break; case "highHumidityTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_highhumidity, station.alltimerecarray[WeatherStation.AT_highhumidity].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "lowHumidityVal": - station.SetAlltime(WeatherStation.AT_lowhumidity, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowhumidity].timestamp); + station.SetAlltime(WeatherStation.AT_lowhumidity, double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowhumidity].timestamp); break; case "lowHumidityTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_lowhumidity, station.alltimerecarray[WeatherStation.AT_lowhumidity].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "highBarometerVal": - station.SetAlltime(WeatherStation.AT_highpress, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_highpress].timestamp); + station.SetAlltime(WeatherStation.AT_highpress, double.Parse(value), station.alltimerecarray[WeatherStation.AT_highpress].timestamp); break; case "highBarometerTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_highpress, station.alltimerecarray[WeatherStation.AT_highpress].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "lowBarometerVal": - station.SetAlltime(WeatherStation.AT_lowpress, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowpress].timestamp); + station.SetAlltime(WeatherStation.AT_lowpress, double.Parse(value), station.alltimerecarray[WeatherStation.AT_lowpress].timestamp); break; case "lowBarometerTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_lowpress, station.alltimerecarray[WeatherStation.AT_lowpress].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "highGustVal": - station.SetAlltime(WeatherStation.AT_highgust, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_highgust].timestamp); + station.SetAlltime(WeatherStation.AT_highgust, double.Parse(value), station.alltimerecarray[WeatherStation.AT_highgust].timestamp); break; case "highGustTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_highgust, station.alltimerecarray[WeatherStation.AT_highgust].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "highWindVal": - station.SetAlltime(WeatherStation.AT_highwind, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_highwind].timestamp); + station.SetAlltime(WeatherStation.AT_highwind, double.Parse(value), station.alltimerecarray[WeatherStation.AT_highwind].timestamp); break; case "highWindTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_highwind, station.alltimerecarray[WeatherStation.AT_highwind].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "highWindRunVal": - station.SetAlltime(WeatherStation.AT_highwindrun, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_highwindrun].timestamp); + station.SetAlltime(WeatherStation.AT_highwindrun, double.Parse(value), station.alltimerecarray[WeatherStation.AT_highwindrun].timestamp); break; case "highWindRunTime": station.SetAlltime(WeatherStation.AT_highwindrun, station.alltimerecarray[WeatherStation.AT_highwindrun].value, station.ddmmyyStrToDate(value)); break; case "highRainRateVal": - station.SetAlltime(WeatherStation.AT_highrainrate, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_highrainrate].timestamp); + station.SetAlltime(WeatherStation.AT_highrainrate, double.Parse(value), station.alltimerecarray[WeatherStation.AT_highrainrate].timestamp); break; case "highRainRateTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_highrainrate, station.alltimerecarray[WeatherStation.AT_highrainrate].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "highHourlyRainVal": - station.SetAlltime(WeatherStation.AT_hourlyrain, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_hourlyrain].timestamp); + station.SetAlltime(WeatherStation.AT_hourlyrain, double.Parse(value), station.alltimerecarray[WeatherStation.AT_hourlyrain].timestamp); break; case "highHourlyRainTime": dt = value.Split('+'); station.SetAlltime(WeatherStation.AT_hourlyrain, station.alltimerecarray[WeatherStation.AT_hourlyrain].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); break; case "highDailyRainVal": - station.SetAlltime(WeatherStation.AT_dailyrain, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_dailyrain].timestamp); + station.SetAlltime(WeatherStation.AT_dailyrain, double.Parse(value), station.alltimerecarray[WeatherStation.AT_dailyrain].timestamp); break; case "highDailyRainTime": station.SetAlltime(WeatherStation.AT_dailyrain, station.alltimerecarray[WeatherStation.AT_dailyrain].value, station.ddmmyyStrToDate(value)); break; case "highMonthlyRainVal": - station.SetAlltime(WeatherStation.AT_wetmonth, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_wetmonth].timestamp); + station.SetAlltime(WeatherStation.AT_wetmonth, double.Parse(value), station.alltimerecarray[WeatherStation.AT_wetmonth].timestamp); break; case "highMonthlyRainTime": dt = value.Split('/'); @@ -1175,13 +1169,13 @@ internal string EditAllTimeRecs(IHttpContext context) station.SetAlltime(WeatherStation.AT_wetmonth, station.alltimerecarray[WeatherStation.AT_wetmonth].value, station.ddmmyyStrToDate(datstr)); break; case "longestDryPeriodVal": - station.SetAlltime(WeatherStation.AT_longestdryperiod, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_longestdryperiod].timestamp); + station.SetAlltime(WeatherStation.AT_longestdryperiod, double.Parse(value), station.alltimerecarray[WeatherStation.AT_longestdryperiod].timestamp); break; case "longestDryPeriodTime": station.SetAlltime(WeatherStation.AT_longestdryperiod, station.alltimerecarray[WeatherStation.AT_longestdryperiod].value, station.ddmmyyStrToDate(value)); break; case "longestWetPeriodVal": - station.SetAlltime(WeatherStation.AT_longestwetperiod, Double.Parse(value), station.alltimerecarray[WeatherStation.AT_longestwetperiod].timestamp); + station.SetAlltime(WeatherStation.AT_longestwetperiod, double.Parse(value), station.alltimerecarray[WeatherStation.AT_longestwetperiod].timestamp); break; case "longestWetPeriodTime": station.SetAlltime(WeatherStation.AT_longestwetperiod, station.alltimerecarray[WeatherStation.AT_longestwetperiod].value, station.ddmmyyStrToDate(value)); @@ -1198,82 +1192,1167 @@ internal string EditAllTimeRecs(IHttpContext context) return "{\"result\":\"" + ((result == 1) ? "Success" : "Failed") + "\"}"; } - internal string GetCurrentCond() - { - return "{\"data\":\"" + webtags.GetCurrCondText() + "\"}"; - } - - internal string EditCurrentCond(IHttpContext context) + internal string EditMonthlyRecs(IHttpContext context) { var request = context.Request; string text; - bool result = true; + + using (var reader = new StreamReader(request.InputStream, request.ContentEncoding)) { - text = reader.ReadToEnd(); + text = Uri.UnescapeDataString(reader.ReadToEnd()); } - - result = SetCurrCondText(text); - - return "{\"result\":\"" + (result ? "Success" : "Failed") + "\"}"; - } - - private bool SetCurrCondText(string currCondText) - { - string fileName = cumulus.AppDir + "currentconditions.txt"; + // Eg "name=2-highTempValvalue=134.6&pk=1" + var newData = text.Split('&'); + var monthField = newData[0].Split('=')[1].Split('-'); + var month = int.Parse(monthField[0]); + var field = monthField[1]; + var value = newData[1].Split('=')[1]; + var result = 1; try { - cumulus.LogMessage("Writing current conditions to file..."); - - System.IO.File.WriteAllText(fileName, currCondText); - return true; + string[] dt; + switch (field) + { + case "highTempVal": + station.SetMonthlyAlltime(WeatherStation.AT_hightemp, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_hightemp, month].timestamp); + break; + case "highTempTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_hightemp, station.monthlyrecarray[WeatherStation.AT_hightemp, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "lowTempVal": + station.SetMonthlyAlltime(WeatherStation.AT_lowtemp, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_lowtemp, month].timestamp); + break; + case "lowTempTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_lowtemp, station.monthlyrecarray[WeatherStation.AT_lowtemp, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "highDewPointVal": + station.SetMonthlyAlltime(WeatherStation.AT_highdewpoint, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_highdewpoint, month].timestamp); + break; + case "highDewPointTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_highdewpoint, station.monthlyrecarray[WeatherStation.AT_highdewpoint, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "lowDewPointVal": + station.SetMonthlyAlltime(WeatherStation.AT_lowdewpoint, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_lowdewpoint, month].timestamp); + break; + case "lowDewPointTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_lowdewpoint, station.monthlyrecarray[WeatherStation.AT_lowdewpoint, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "highApparentTempVal": + station.SetMonthlyAlltime(WeatherStation.AT_highapptemp, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_highapptemp, month].timestamp); + break; + case "highApparentTempTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_highapptemp, station.monthlyrecarray[WeatherStation.AT_highapptemp, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "lowApparentTempVal": + station.SetMonthlyAlltime(WeatherStation.AT_lowapptemp, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_lowapptemp, month].timestamp); + break; + case "lowApparentTempTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_lowapptemp, station.monthlyrecarray[WeatherStation.AT_lowapptemp, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "lowWindChillVal": + station.SetMonthlyAlltime(WeatherStation.AT_lowchill, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_lowchill, month].timestamp); + break; + case "lowWindChillTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_lowchill, station.monthlyrecarray[WeatherStation.AT_lowchill, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "highHeatIndexVal": + station.SetMonthlyAlltime(WeatherStation.AT_highheatindex, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_highheatindex, month].timestamp); + break; + case "highHeatIndexTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_highheatindex, station.monthlyrecarray[WeatherStation.AT_highheatindex, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "highMinTempVal": + station.SetMonthlyAlltime(WeatherStation.AT_highmintemp, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_highmintemp, month].timestamp); + break; + case "highMinTempTime": + station.SetMonthlyAlltime(WeatherStation.AT_highmintemp, station.monthlyrecarray[WeatherStation.AT_highmintemp, month].value, station.ddmmyyStrToDate(value)); + break; + case "lowMaxTempVal": + station.SetMonthlyAlltime(WeatherStation.AT_lowmaxtemp, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_lowmaxtemp, month].timestamp); + break; + case "lowMaxTempTime": + station.SetMonthlyAlltime(WeatherStation.AT_lowmaxtemp, station.monthlyrecarray[WeatherStation.AT_lowmaxtemp, month].value, station.ddmmyyStrToDate(value)); + break; + case "highDailyTempRangeVal": + station.SetMonthlyAlltime(WeatherStation.AT_highdailytemprange, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_highdailytemprange, month].timestamp); + break; + case "highDailyTempRangeTime": + station.SetMonthlyAlltime(WeatherStation.AT_highdailytemprange, station.monthlyrecarray[WeatherStation.AT_highdailytemprange, month].value, station.ddmmyyStrToDate(value)); + break; + case "lowDailyTempRangeVal": + station.SetMonthlyAlltime(WeatherStation.AT_lowdailytemprange, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_lowdailytemprange, month].timestamp); + break; + case "lowDailyTempRangeTime": + station.SetMonthlyAlltime(WeatherStation.AT_lowdailytemprange, station.monthlyrecarray[WeatherStation.AT_lowdailytemprange, month].value, station.ddmmyyStrToDate(value)); + break; + case "highHumidityVal": + station.SetMonthlyAlltime(WeatherStation.AT_highhumidity, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_highhumidity, month].timestamp); + break; + case "highHumidityTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_highhumidity, station.monthlyrecarray[WeatherStation.AT_highhumidity, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "lowHumidityVal": + station.SetMonthlyAlltime(WeatherStation.AT_lowhumidity, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_lowhumidity, month].timestamp); + break; + case "lowHumidityTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_lowhumidity, station.monthlyrecarray[WeatherStation.AT_lowhumidity, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "highBarometerVal": + station.SetMonthlyAlltime(WeatherStation.AT_highpress, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_highpress, month].timestamp); + break; + case "highBarometerTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_highpress, station.monthlyrecarray[WeatherStation.AT_highpress, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "lowBarometerVal": + station.SetMonthlyAlltime(WeatherStation.AT_lowpress, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_lowpress, month].timestamp); + break; + case "lowBarometerTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_lowpress, station.monthlyrecarray[WeatherStation.AT_lowpress, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "highGustVal": + station.SetMonthlyAlltime(WeatherStation.AT_highgust, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_highgust, month].timestamp); + break; + case "highGustTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_highgust, station.monthlyrecarray[WeatherStation.AT_highgust, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "highWindVal": + station.SetMonthlyAlltime(WeatherStation.AT_highwind, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_highwind, month].timestamp); + break; + case "highWindTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_highwind, station.monthlyrecarray[WeatherStation.AT_highwind, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "highWindRunVal": + station.SetMonthlyAlltime(WeatherStation.AT_highwindrun, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_highwindrun, month].timestamp); + break; + case "highWindRunTime": + station.SetMonthlyAlltime(WeatherStation.AT_highwindrun, station.monthlyrecarray[WeatherStation.AT_highwindrun, month].value, station.ddmmyyStrToDate(value)); + break; + case "highRainRateVal": + station.SetMonthlyAlltime(WeatherStation.AT_highrainrate, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_highrainrate, month].timestamp); + break; + case "highRainRateTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_highrainrate, station.monthlyrecarray[WeatherStation.AT_highrainrate, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "highHourlyRainVal": + station.SetMonthlyAlltime(WeatherStation.AT_hourlyrain, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_hourlyrain, month].timestamp); + break; + case "highHourlyRainTime": + dt = value.Split('+'); + station.SetMonthlyAlltime(WeatherStation.AT_hourlyrain, station.monthlyrecarray[WeatherStation.AT_hourlyrain, month].value, station.ddmmyyhhmmStrToDate(dt[0], dt[1])); + break; + case "highDailyRainVal": + station.SetMonthlyAlltime(WeatherStation.AT_dailyrain, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_dailyrain, month].timestamp); + break; + case "highDailyRainTime": + station.SetMonthlyAlltime(WeatherStation.AT_dailyrain, station.monthlyrecarray[WeatherStation.AT_dailyrain, month].value, station.ddmmyyStrToDate(value)); + break; + case "highMonthlyRainVal": + station.SetMonthlyAlltime(WeatherStation.AT_wetmonth, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_wetmonth, month].timestamp); + break; + case "highMonthlyRainTime": + dt = value.Split('/'); + var datstr = "01/" + dt[1] + "/" + dt[0].Substring(2, 2); + station.SetMonthlyAlltime(WeatherStation.AT_wetmonth, station.monthlyrecarray[WeatherStation.AT_wetmonth, month].value, station.ddmmyyStrToDate(datstr)); + break; + case "longestDryPeriodVal": + station.SetMonthlyAlltime(WeatherStation.AT_longestdryperiod, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_longestdryperiod, month].timestamp); + break; + case "longestDryPeriodTime": + station.SetMonthlyAlltime(WeatherStation.AT_longestdryperiod, station.monthlyrecarray[WeatherStation.AT_longestdryperiod, month].value, station.ddmmyyStrToDate(value)); + break; + case "longestWetPeriodVal": + station.SetMonthlyAlltime(WeatherStation.AT_longestwetperiod, double.Parse(value), station.monthlyrecarray[WeatherStation.AT_longestwetperiod, month].timestamp); + break; + case "longestWetPeriodTime": + station.SetMonthlyAlltime(WeatherStation.AT_longestwetperiod, station.monthlyrecarray[WeatherStation.AT_longestwetperiod, month].value, station.ddmmyyStrToDate(value)); + break; + default: + result = 0; + break; + } } - catch (Exception e) + catch { - cumulus.LogMessage("Error writing current conditions to file - " + e.Message); - return false; + result = 0; } + return "{\"result\":\"" + ((result == 1) ? "Success" : "Failed") + "\"}"; } - internal class JsonEditRainData - { - public double raintoday { get; set; } - public double raincounter { get; set; } - public double startofdayrain { get; set; } - public double rainmult { get; set; } - } - private void AddLastHourRainEntry(DateTime ts, double rain) + internal string GetMonthlyRecData() { - LastHourRainLog lasthourrain = new LastHourRainLog(ts, rain); + const string timeStampFormat = "dd/MM/yy HH:mm"; + const string dateStampFormat = "dd/MM/yy"; - HourRainLog.Add(lasthourrain); + var json = "{"; + for (var m = 1; m <= 12; m++) + { + // Records - Temperature values + json += $"\"{m}-highTempVal\":\"" + station.monthlyrecarray[WeatherStation.AT_hightemp, m].value.ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowTempVal\":\"" + station.monthlyrecarray[WeatherStation.AT_lowtemp, m].value.ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highDewPointVal\":\"" + station.monthlyrecarray[WeatherStation.AT_highdewpoint, m].value.ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowDewPointVal\":\"" + station.monthlyrecarray[WeatherStation.AT_lowdewpoint, m].value.ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highApparentTempVal\":\"" + station.monthlyrecarray[WeatherStation.AT_highapptemp, m].value.ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowApparentTempVal\":\"" + station.monthlyrecarray[WeatherStation.AT_lowapptemp, m].value.ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowWindChillVal\":\"" + station.monthlyrecarray[WeatherStation.AT_lowchill, m].value.ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highHeatIndexVal\":\"" + station.monthlyrecarray[WeatherStation.AT_highheatindex, m].value.ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highMinTempVal\":\"" + station.monthlyrecarray[WeatherStation.AT_highmintemp, m].value.ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowMaxTempVal\":\"" + station.monthlyrecarray[WeatherStation.AT_lowmaxtemp, m].value.ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highDailyTempRangeVal\":\"" + station.monthlyrecarray[WeatherStation.AT_highdailytemprange, m].value.ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowDailyTempRangeVal\":\"" + station.monthlyrecarray[WeatherStation.AT_lowdailytemprange, m].value.ToString(cumulus.TempFormat) + "\","; + // Records - Temperature timestamps + json += $"\"{m}-highTempTime\":\"" + station.monthlyrecarray[WeatherStation.AT_hightemp, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowTempTime\":\"" + station.monthlyrecarray[WeatherStation.AT_lowtemp, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-highDewPointTime\":\"" + station.monthlyrecarray[WeatherStation.AT_highdewpoint, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowDewPointTime\":\"" + station.monthlyrecarray[WeatherStation.AT_lowdewpoint, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-highApparentTempTime\":\"" + station.monthlyrecarray[WeatherStation.AT_highapptemp, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowApparentTempTime\":\"" + station.monthlyrecarray[WeatherStation.AT_lowapptemp, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowWindChillTime\":\"" + station.monthlyrecarray[WeatherStation.AT_lowchill, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-highHeatIndexTime\":\"" + station.monthlyrecarray[WeatherStation.AT_highheatindex, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-highMinTempTime\":\"" + station.monthlyrecarray[WeatherStation.AT_highmintemp, m].timestamp.ToString(dateStampFormat) + "\","; + json += $"\"{m}-lowMaxTempTime\":\"" + station.monthlyrecarray[WeatherStation.AT_lowmaxtemp, m].timestamp.ToString(dateStampFormat) + "\","; + json += $"\"{m}-highDailyTempRangeTime\":\"" + station.monthlyrecarray[WeatherStation.AT_highdailytemprange, m].timestamp.ToString(dateStampFormat) + "\","; + json += $"\"{m}-lowDailyTempRangeTime\":\"" + station.monthlyrecarray[WeatherStation.AT_lowdailytemprange, m].timestamp.ToString(dateStampFormat) + "\","; + // Records - Humidity values + json += $"\"{m}-highHumidityVal\":\"" + station.monthlyrecarray[WeatherStation.AT_highhumidity, m].value.ToString(cumulus.HumFormat) + "\","; + json += $"\"{m}-lowHumidityVal\":\"" + station.monthlyrecarray[WeatherStation.AT_lowhumidity, m].value.ToString(cumulus.HumFormat) + "\","; + // Records - Humidity times + json += $"\"{m}-highHumidityTime\":\"" + station.monthlyrecarray[WeatherStation.AT_highhumidity, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowHumidityTime\":\"" + station.monthlyrecarray[WeatherStation.AT_lowhumidity, m].timestamp.ToString(timeStampFormat) + "\","; + // Records - Pressure values + json += $"\"{m}-highBarometerVal\":\"" + station.monthlyrecarray[WeatherStation.AT_highpress, m].value.ToString(cumulus.PressFormat) + "\","; + json += $"\"{m}-lowBarometerVal\":\"" + station.monthlyrecarray[WeatherStation.AT_lowpress, m].value.ToString(cumulus.PressFormat) + "\","; + // Records - Pressure times + json += $"\"{m}-highBarometerTime\":\"" + station.monthlyrecarray[WeatherStation.AT_highpress, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowBarometerTime\":\"" + station.monthlyrecarray[WeatherStation.AT_lowpress, m].timestamp.ToString(timeStampFormat) + "\","; + // Records - Wind values + json += $"\"{m}-highGustVal\":\"" + station.monthlyrecarray[WeatherStation.AT_highgust, m].value.ToString(cumulus.WindFormat) + "\","; + json += $"\"{m}-highWindVal\":\"" + station.monthlyrecarray[WeatherStation.AT_highwind, m].value.ToString(cumulus.WindFormat) + "\","; + json += $"\"{m}-highWindRunVal\":\"" + station.monthlyrecarray[WeatherStation.AT_highwindrun, m].value.ToString(cumulus.WindRunFormat) + "\","; + // Records - Wind times + json += $"\"{m}-highGustTime\":\"" + station.monthlyrecarray[WeatherStation.AT_highgust, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-highWindTime\":\"" + station.monthlyrecarray[WeatherStation.AT_highwind, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-highWindRunTime\":\"" + station.monthlyrecarray[WeatherStation.AT_highwindrun, m].timestamp.ToString(dateStampFormat) + "\","; + // Records - Rain values + json += $"\"{m}-highRainRateVal\":\"" + station.monthlyrecarray[WeatherStation.AT_highrainrate, m].value.ToString(cumulus.RainFormat) + "\","; + json += $"\"{m}-highHourlyRainVal\":\"" + station.monthlyrecarray[WeatherStation.AT_hourlyrain, m].value.ToString(cumulus.RainFormat) + "\","; + json += $"\"{m}-highDailyRainVal\":\"" + station.monthlyrecarray[WeatherStation.AT_dailyrain, m].value.ToString(cumulus.RainFormat) + "\","; + json += $"\"{m}-highMonthlyRainVal\":\"" + station.monthlyrecarray[WeatherStation.AT_wetmonth, m].value.ToString(cumulus.RainFormat) + "\","; + json += $"\"{m}-longestDryPeriodVal\":\"" + station.monthlyrecarray[WeatherStation.AT_longestdryperiod, m].value.ToString("f0") + "\","; + json += $"\"{m}-longestWetPeriodVal\":\"" + station.monthlyrecarray[WeatherStation.AT_longestwetperiod, m].value.ToString("f0") + "\","; + // Records - Rain times + json += $"\"{m}-highRainRateTime\":\"" + station.monthlyrecarray[WeatherStation.AT_highrainrate, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-highHourlyRainTime\":\"" + station.monthlyrecarray[WeatherStation.AT_hourlyrain, m].timestamp.ToString(timeStampFormat) + "\","; + json += $"\"{m}-highDailyRainTime\":\"" + station.monthlyrecarray[WeatherStation.AT_dailyrain, m].timestamp.ToString(dateStampFormat) + "\","; + json += $"\"{m}-highMonthlyRainTime\":\"" + station.monthlyrecarray[WeatherStation.AT_wetmonth, m].timestamp.ToString("yyyy/MM") + "\","; + json += $"\"{m}-longestDryPeriodTime\":\"" + station.monthlyrecarray[WeatherStation.AT_longestdryperiod, m].timestamp.ToString(dateStampFormat) + "\","; + json += $"\"{m}-longestWetPeriodTime\":\"" + station.monthlyrecarray[WeatherStation.AT_longestwetperiod, m].timestamp.ToString(dateStampFormat) + "\","; + + } + json = json.Remove(json.Length - 1); + json += "}"; + + return json; + } + + internal string GetMonthlyRecDayFile() + { + const string timeStampFormat = "dd/MM/yy HH:mm"; + const string dateStampFormat = "dd/MM/yy"; + + var linenum = 0; + var highTempVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowTempVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var highDewPtVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowDewPtVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var highAppTempVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowAppTempVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var lowWindChillVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var highHeatIndVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highMinTempVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowMaxTempVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var highTempRangeVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowTempRangeVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var highHumVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowHumVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var highBaroVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowBaroVal = new double[] { 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999 }; + var highGustVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highWindVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highWindRunVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highRainRateVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highRainHourVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highRainDayVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highRainMonthVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var dryPeriodVal = new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + var wetPeriodVal = new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + var thisDate = new DateTime(1900, 01, 01); + var highTempTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowTempTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highDewPtTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowDewPtTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highAppTempTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowAppTempTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowWindChillTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highHeatIndTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highMinTempTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowMaxTempTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highTempRangeTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowTempRangeTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highHumTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowHumTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highBaroTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowBaroTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highGustTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highWindTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highWindRunTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highRainRateTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highRainHourTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highRainDayTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highRainMonthTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var dryPeriodTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var wetPeriodTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + + var rainThisMonth = 0.0; + var currentDryPeriod = 0; + var currentWetPeriod = 0; + var isDryNow = false; + var thisDateDry = thisDate; + var thisDateWet = thisDate; + var json = "{"; + + var rainThreshold = 0.0; + if (cumulus.RainDayThreshold > -1) + rainThreshold = cumulus.RainDayThreshold; + + var watch = System.Diagnostics.Stopwatch.StartNew(); + + // Read the dayfile and extract the records from there + if (File.Exists(cumulus.DayFile)) + { + try + { + var dayfile = File.ReadAllLines(cumulus.DayFile); + + foreach (var line in dayfile) + { + linenum++; + var st = new List(Regex.Split(line, CultureInfo.CurrentCulture.TextInfo.ListSeparator)); + + if (st.Count <= 0) continue; + + var datestr = st[0]; + var loggedDate = station.ddmmyyStrToDate(datestr); + var monthOffset = loggedDate.Month - 1; + double valDbl, valDbl2; + + // This assumes the day file is in date order! + if (thisDate.Month != loggedDate.Month) + { + // monthly rain + if (rainThisMonth > highRainMonthVal[monthOffset]) + { + highRainMonthVal[monthOffset] = rainThisMonth; + highRainMonthTime[monthOffset] = thisDate; + } + // reset the date and counter for a new month + thisDate = loggedDate; + rainThisMonth = 0; + } + // hi temp + if (double.TryParse(st[6], out valDbl) && valDbl > highTempVal[monthOffset]) + { + highTempVal[monthOffset] = valDbl; + highTempTime[monthOffset] = GetDateTime(loggedDate, st[7]); + } + // lo temp + if (double.TryParse(st[4], out valDbl) && valDbl < lowTempVal[monthOffset]) + { + lowTempVal[monthOffset] = valDbl; + lowTempTime[monthOffset] = GetDateTime(loggedDate, st[5]); + } + // hi dewpt + if (double.TryParse(st[35], out valDbl) && valDbl > highDewPtVal[monthOffset]) + { + highDewPtVal[monthOffset] = valDbl; + highDewPtTime[monthOffset] = GetDateTime(loggedDate, st[36]); + } + // lo dewpt + if (double.TryParse(st[37], out valDbl) && valDbl < lowDewPtVal[monthOffset]) + { + lowDewPtVal[monthOffset] = valDbl; + lowDewPtTime[monthOffset] = GetDateTime(loggedDate, st[38]); + } + // hi app temp + if (double.TryParse(st[27], out valDbl) && valDbl > highAppTempVal[monthOffset]) + { + highAppTempVal[monthOffset] = valDbl; + highAppTempTime[monthOffset] = GetDateTime(loggedDate, st[28]); + } + // lo app temp + if (double.TryParse(st[29], out valDbl) && valDbl < lowAppTempVal[monthOffset]) + { + lowAppTempVal[monthOffset] = valDbl; + lowAppTempTime[monthOffset] = GetDateTime(loggedDate, st[30]); + } + // lo wind chill + if (double.TryParse(st[33], out valDbl) && valDbl < lowWindChillVal[monthOffset]) + { + lowWindChillVal[monthOffset] = valDbl; + lowWindChillTime[monthOffset] = GetDateTime(loggedDate, st[34]); + } + // hi heat index + if (double.TryParse(st[25], out valDbl) && valDbl > highHeatIndVal[monthOffset]) + { + highHeatIndVal[monthOffset] = valDbl; + highHeatIndTime[monthOffset] = GetDateTime(loggedDate, st[26]); + } + // hi min temp + if (double.TryParse(st[4], out valDbl) && valDbl > highMinTempVal[monthOffset]) + { + highMinTempVal[monthOffset] = valDbl; + highMinTempTime[monthOffset] = loggedDate; + } + // lo max temp + if (double.TryParse(st[6], out valDbl) && valDbl < lowMaxTempVal[monthOffset]) + { + lowMaxTempVal[monthOffset] = valDbl; + lowMaxTempTime[monthOffset] = loggedDate; + } + // temp ranges + if (double.TryParse(st[6], out valDbl) && double.TryParse(st[4], out valDbl2)) + { + // hi temp range + if ((valDbl - valDbl2) > highTempRangeVal[monthOffset]) + { + highTempRangeVal[monthOffset] = valDbl - valDbl2; + highTempRangeTime[monthOffset] = loggedDate; + } + // lo temp range + if ((valDbl - valDbl2) < lowTempRangeVal[monthOffset]) + { + lowTempRangeVal[monthOffset] = valDbl - valDbl2; + lowTempRangeTime[monthOffset] = loggedDate; + } + } + // hi humidity + if (double.TryParse(st[21], out valDbl) && valDbl > highHumVal[monthOffset]) + { + highHumVal[monthOffset] = valDbl; + highHumTime[monthOffset] = GetDateTime(loggedDate, st[22]); + } + // lo humidity + if (double.TryParse(st[19], out valDbl) && valDbl < lowHumVal[monthOffset]) + { + lowHumVal[monthOffset] = valDbl; + lowHumTime[monthOffset] = GetDateTime(loggedDate, st[20]); + } + // hi baro + if (double.TryParse(st[10], out valDbl) && valDbl > highBaroVal[monthOffset]) + { + highBaroVal[monthOffset] = valDbl; + highBaroTime[monthOffset] = GetDateTime(loggedDate, st[11]); + } + // lo baro + if (double.TryParse(st[8], out valDbl) && valDbl < lowBaroVal[monthOffset]) + { + lowBaroVal[monthOffset] = valDbl; + lowBaroTime[monthOffset] = GetDateTime(loggedDate, st[9]); + } + // hi gust + if (double.TryParse(st[1], out valDbl) && valDbl > highGustVal[monthOffset]) + { + highGustVal[monthOffset] = valDbl; + highGustTime[monthOffset] = GetDateTime(loggedDate, st[3]); + } + // hi wind + if (double.TryParse(st[17], out valDbl) && valDbl > highWindVal[monthOffset]) + { + highWindVal[monthOffset] = valDbl; + highWindTime[monthOffset] = GetDateTime(loggedDate, st[18]); + } + // hi wind run + if (double.TryParse(st[16], out valDbl) && valDbl > highWindRunVal[monthOffset]) + { + highWindRunVal[monthOffset] = valDbl; + highWindRunTime[monthOffset] = loggedDate; + } + // hi rain rate + if (double.TryParse(st[12], out valDbl) && valDbl > highRainRateVal[monthOffset]) + { + highRainRateVal[monthOffset] = valDbl; + highRainRateTime[monthOffset] = GetDateTime(loggedDate, st[13]); + } + // hi rain hour + if (double.TryParse(st[31], out valDbl) && valDbl > highRainHourVal[monthOffset]) + { + highRainHourVal[monthOffset] = valDbl; + highRainHourTime[monthOffset] = GetDateTime(loggedDate, st[32]); + } + if (double.TryParse(st[14], out valDbl)) + { + // hi rain day + if (valDbl > highRainDayVal[monthOffset]) + { + highRainDayVal[monthOffset] = valDbl; + highRainDayTime[monthOffset] = loggedDate; + } + + // monthly rain + rainThisMonth += valDbl; + + // dry/wet period + if (valDbl > rainThreshold) + { + if (isDryNow) + { + currentWetPeriod = 1; + isDryNow = false; + if (currentDryPeriod > dryPeriodVal[monthOffset]) + { + dryPeriodVal[monthOffset] = currentDryPeriod; + dryPeriodTime[monthOffset] = thisDateDry; + } + currentDryPeriod = 0; + } + else + { + currentWetPeriod++; + thisDateWet = loggedDate; + } + } + else + { + if (isDryNow) + { + currentDryPeriod++; + thisDateDry = loggedDate; + } + else + { + currentDryPeriod = 1; + isDryNow = true; + if (currentWetPeriod > wetPeriodVal[monthOffset]) + { + wetPeriodVal[monthOffset] = currentWetPeriod; + wetPeriodTime[monthOffset] = thisDateWet; + } + currentWetPeriod = 0; + } + } + } + } + + for (var i = 0; i < 12; i++) + { + var m = i + 1; + json += $"\"{m}-highTempValDayfile\":\"" + highTempVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highTempTimeDayfile\":\"" + highTempTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowTempValDayfile\":\"" + lowTempVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowTempTimeDayfile\":\"" + lowTempTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highDewPointValDayfile\":\"" + highDewPtVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highDewPointTimeDayfile\":\"" + highDewPtTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowDewPointValDayfile\":\"" + lowDewPtVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowDewPointTimeDayfile\":\"" + lowDewPtTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highApparentTempValDayfile\":\"" + highAppTempVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highApparentTempTimeDayfile\":\"" + highAppTempTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowApparentTempValDayfile\":\"" + lowAppTempVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowApparentTempTimeDayfile\":\"" + lowAppTempTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowWindChillValDayfile\":\"" + lowWindChillVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowWindChillTimeDayfile\":\"" + lowWindChillTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highHeatIndexValDayfile\":\"" + highHeatIndVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highHeatIndexTimeDayfile\":\"" + highHeatIndTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highMinTempValDayfile\":\"" + highMinTempVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highMinTempTimeDayfile\":\"" + highMinTempTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-lowMaxTempValDayfile\":\"" + lowMaxTempVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowMaxTempTimeDayfile\":\"" + lowMaxTempTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-highDailyTempRangeValDayfile\":\"" + highTempRangeVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highDailyTempRangeTimeDayfile\":\"" + highTempRangeTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-lowDailyTempRangeValDayfile\":\"" + lowTempRangeVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowDailyTempRangeTimeDayfile\":\"" + lowTempRangeTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-highHumidityValDayfile\":\"" + highHumVal[i].ToString(cumulus.HumFormat) + "\","; + json += $"\"{m}-highHumidityTimeDayfile\":\"" + highHumTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowHumidityValDayfile\":\"" + lowHumVal[i].ToString(cumulus.HumFormat) + "\","; + json += $"\"{m}-lowHumidityTimeDayfile\":\"" + lowHumTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highBarometerValDayfile\":\"" + highBaroVal[i].ToString(cumulus.PressFormat) + "\","; + json += $"\"{m}-highBarometerTimeDayfile\":\"" + highBaroTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowBarometerValDayfile\":\"" + lowBaroVal[i].ToString(cumulus.PressFormat) + "\","; + json += $"\"{m}-lowBarometerTimeDayfile\":\"" + lowBaroTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highGustValDayfile\":\"" + highGustVal[i].ToString(cumulus.WindFormat) + "\","; + json += $"\"{m}-highGustTimeDayfile\":\"" + highGustTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highWindValDayfile\":\"" + highWindVal[i].ToString(cumulus.WindFormat) + "\","; + json += $"\"{m}-highWindTimeDayfile\":\"" + highWindTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highWindRunValDayfile\":\"" + highWindRunVal[i].ToString(cumulus.WindRunFormat) + "\","; + json += $"\"{m}-highWindRunTimeDayfile\":\"" + highWindRunTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-highRainRateValDayfile\":\"" + highRainRateVal[i].ToString(cumulus.RainFormat) + "\","; + json += $"\"{m}-highRainRateTimeDayfile\":\"" + highRainRateTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highHourlyRainValDayfile\":\"" + highRainHourVal[i].ToString(cumulus.RainFormat) + "\","; + json += $"\"{m}-highHourlyRainTimeDayfile\":\"" + highRainHourTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highDailyRainValDayfile\":\"" + highRainDayVal[i].ToString(cumulus.RainFormat) + "\","; + json += $"\"{m}-highDailyRainTimeDayfile\":\"" + highRainDayTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-highMonthlyRainValDayfile\":\"" + highRainMonthVal[i].ToString(cumulus.RainFormat) + "\","; + json += $"\"{m}-highMonthlyRainTimeDayfile\":\"" + highRainMonthTime[i].ToString("yyyy/MM") + "\","; + json += $"\"{m}-longestDryPeriodValDayfile\":\"" + dryPeriodVal[i].ToString() + "\","; + json += $"\"{m}-longestDryPeriodTimeDayfile\":\"" + dryPeriodTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-longestWetPeriodValDayfile\":\"" + wetPeriodVal[i].ToString() + "\","; + json += $"\"{m}-longestWetPeriodTimeDayfile\":\"" + wetPeriodTime[i].ToString(dateStampFormat) + "\","; + } + json = json.Remove(json.Length - 1); + json += "}"; + } + catch (Exception e) + { + cumulus.LogMessage("Error on line " + linenum + " of " + cumulus.DayFile + ": " + e.Message); + } + } + else + { + cumulus.LogMessage("Error failed to find day file: " + cumulus.DayFile); + } + + watch.Stop(); + var elapsed = watch.ElapsedMilliseconds; + cumulus.LogDebugMessage($"Monthly recs editor Dayfile load = {elapsed} ms"); + + return json; + } + + internal string GetMonthlyRecLogFile() + { + const string timeStampFormat = "dd/MM/yy HH:mm"; + const string dateStampFormat = "dd/MM/yy"; + + var json = "{"; + var datefrom = DateTime.Parse(cumulus.RecordsBeganDate); + datefrom = new DateTime(datefrom.Year, datefrom.Month, 1, 0, 0, 0); + var dateto = DateTime.Now; + dateto = new DateTime(dateto.Year, dateto.Month, 1, 0, 0, 0); + var filedate = datefrom; + + var logFile = cumulus.GetLogFileName(filedate); + var started = false; + var finished = false; + var lastentrydate = datefrom; + + var currentDay = datefrom; + double dayHighTemp = -999; + double dayLowTemp = 999; + double dayWindRun = 0; + double dayRain = 0; + + var isDryNow = false; + var currentDryPeriod = 0; + var currentWetPeriod = 0; + + var rainThreshold = 0.0; + if (cumulus.RainDayThreshold > -1) + rainThreshold = cumulus.RainDayThreshold; + + var highTempVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowTempVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var highDewPtVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowDewPtVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var highAppTempVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowAppTempVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var lowWindChillVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var highHeatIndVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highMinTempVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowMaxTempVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var highTempRangeVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowTempRangeVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var highHumVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowHumVal = new double[] { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999 }; + var highBaroVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var lowBaroVal = new double[] { 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999 }; + var highGustVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highWindVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highWindRunVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highRainRateVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highRainHourVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highRainDayVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var highRainMonthVal = new double[] { -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 }; + var dryPeriodVal = new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + var wetPeriodVal = new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + var thisDate = new DateTime(1900, 01, 01); + var highTempTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowTempTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highDewPtTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowDewPtTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highAppTempTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowAppTempTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowWindChillTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highHeatIndTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highMinTempTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowMaxTempTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highTempRangeTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowTempRangeTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highHumTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowHumTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highBaroTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var lowBaroTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highGustTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highWindTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highWindRunTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highRainRateTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highRainHourTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highRainDayTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var highRainMonthTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var dryPeriodTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + var wetPeriodTime = new[] { thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate, thisDate }; + + var thisDateDry = thisDate; + var thisDateWet = thisDate; + + var totalRainfall = 0.0; + + hourRainLog.Clear(); + + var watch = System.Diagnostics.Stopwatch.StartNew(); + + while (!finished) + { + double monthlyRain = 0; + + if (File.Exists(logFile)) + { + cumulus.LogDebugMessage($"GetMonthlyTimeRecLogFile: Processing log file - {logFile}"); + var linenum = 0; + try + { + var logfile = File.ReadAllLines(logFile); + foreach (var line in logfile) + { + // process each record in the file + linenum++; + //var st = new List(Regex.Split(line, CultureInfo.CurrentCulture.TextInfo.ListSeparator)); + // Regex is very expensive, let's assume the separator is always a single character + var st = new List(line.Split((CultureInfo.CurrentCulture.TextInfo.ListSeparator)[0])); + var entrydate = station.ddmmyyhhmmStrToDate(st[0], st[1]); + // We need to work in meto dates not clock dates for day hi/lows + var metoDate = entrydate.AddHours(cumulus.GetHourInc()); + var monthOffset = metoDate.Month - 1; + double valDbl; + + if (!started) + { + lastentrydate = entrydate; + currentDay = metoDate; + started = true; + } + + var outsidetemp = double.Parse(st[2]); + var hum = double.Parse(st[3]); + var dewpoint = double.Parse(st[4]); + var speed = double.Parse(st[5]); + var gust = double.Parse(st[6]); + var rainrate = double.Parse(st[8]); + var raintoday = double.Parse(st[9]); + var pressure = double.Parse(st[10]); + if (st.Count > 15 && double.TryParse(st[15], out valDbl)) + { + // low chill + if (valDbl < lowWindChillVal[monthOffset]) + { + lowWindChillVal[monthOffset] = valDbl; + lowWindChillTime[monthOffset] = entrydate; + } + + } + if (st.Count > 16 && double.TryParse(st[16], out valDbl)) + { + // hi heat + if (valDbl > highHeatIndVal[monthOffset]) + { + highHeatIndVal[monthOffset] = valDbl; + highHeatIndTime[monthOffset] = entrydate; + } + } + if (st.Count > 21 && double.TryParse(st[21], out valDbl)) + { + // hi appt + if (valDbl > highAppTempVal[monthOffset]) + { + highAppTempVal[monthOffset] = valDbl; + highAppTempTime[monthOffset] = entrydate; + } + // lo appt + if (valDbl < lowAppTempVal[monthOffset]) + { + lowAppTempVal[monthOffset] = valDbl; + lowAppTempTime[monthOffset] = entrydate; + } + } + // hi temp + if (outsidetemp > highTempVal[monthOffset]) + { + highTempVal[monthOffset] = outsidetemp; + highTempTime[monthOffset] = entrydate; + } + // lo temp + if (outsidetemp < lowTempVal[monthOffset]) + { + lowTempVal[monthOffset] = outsidetemp; + lowTempTime[monthOffset] = entrydate; + } + // hi dewpoint + if (dewpoint > highDewPtVal[monthOffset]) + { + highDewPtVal[monthOffset] = dewpoint; + highDewPtTime[monthOffset] = entrydate; + } + // low dewpoint + if (dewpoint < lowDewPtVal[monthOffset]) + { + lowDewPtVal[monthOffset] = dewpoint; + lowDewPtTime[monthOffset] = entrydate; + } + // hi hum + if (hum > highHumVal[monthOffset]) + { + highHumVal[monthOffset] = hum; + highHumTime[monthOffset] = entrydate; + } + // lo hum + if (hum < lowHumVal[monthOffset]) + { + lowHumVal[monthOffset] = hum; + lowHumTime[monthOffset] = entrydate; + } + // hi baro + if (pressure > highBaroVal[monthOffset]) + { + highBaroVal[monthOffset] = pressure; + highBaroTime[monthOffset] = entrydate; + } + // lo hum + if (pressure < lowBaroVal[monthOffset]) + { + lowBaroVal[monthOffset] = pressure; + lowBaroTime[monthOffset] = entrydate; + } + // hi gust + if (gust > highGustVal[monthOffset]) + { + highGustVal[monthOffset] = gust; + highGustTime[monthOffset] = entrydate; + } + // hi wind + if (speed > highWindVal[monthOffset]) + { + highWindVal[monthOffset] = speed; + highWindTime[monthOffset] = entrydate; + } + // hi rain rate + if (rainrate > highRainRateVal[monthOffset]) + { + highRainRateVal[monthOffset] = rainrate; + highRainRateTime[monthOffset] = entrydate; + } + + if (monthlyRain > highRainMonthVal[monthOffset]) + { + highRainMonthVal[monthOffset] = monthlyRain; + highRainMonthTime[monthOffset] = entrydate; + } + + // same meto day + if (currentDay.Day == metoDate.Day && currentDay.Month == metoDate.Month && currentDay.Year == metoDate.Year) + { + if (outsidetemp > dayHighTemp) + dayHighTemp = outsidetemp; + + if (outsidetemp < dayLowTemp) + dayLowTemp = outsidetemp; + + if (dayRain < raintoday) + dayRain = raintoday; + + dayWindRun += entrydate.Subtract(lastentrydate).TotalHours * speed; + } + else // new meto day + { + var lastEntryMonthOffset = currentDay.Month - 1; + if (dayHighTemp < lowMaxTempVal[lastEntryMonthOffset]) + { + lowMaxTempVal[lastEntryMonthOffset] = dayHighTemp; + lowMaxTempTime[lastEntryMonthOffset] = currentDay; + } + if (dayLowTemp > highMinTempVal[lastEntryMonthOffset]) + { + highMinTempVal[lastEntryMonthOffset] = dayLowTemp; + highMinTempTime[lastEntryMonthOffset] = currentDay; + } + if (dayHighTemp - dayLowTemp > highTempRangeVal[lastEntryMonthOffset]) + { + highTempRangeVal[lastEntryMonthOffset] = dayHighTemp - dayLowTemp; + highTempRangeTime[lastEntryMonthOffset] = currentDay; + } + if (dayHighTemp - dayLowTemp < lowTempRangeVal[lastEntryMonthOffset]) + { + lowTempRangeVal[lastEntryMonthOffset] = dayHighTemp - dayLowTemp; + lowTempRangeTime[lastEntryMonthOffset] = currentDay; + } + if (dayWindRun > highWindRunVal[lastEntryMonthOffset]) + { + highWindRunVal[lastEntryMonthOffset] = dayWindRun; + highWindRunTime[lastEntryMonthOffset] = currentDay; + } + if (dayRain > highRainDayVal[lastEntryMonthOffset]) + { + highRainDayVal[lastEntryMonthOffset] = dayRain; + highRainDayTime[lastEntryMonthOffset] = currentDay; + } + monthlyRain += dayRain; + + // dry/wet period + if (dayRain > rainThreshold) + { + if (isDryNow) + { + currentWetPeriod = 1; + isDryNow = false; + if (currentDryPeriod > dryPeriodVal[monthOffset]) + { + dryPeriodVal[monthOffset] = currentDryPeriod; + dryPeriodTime[monthOffset] = thisDateDry; + } + currentDryPeriod = 0; + } + else + { + currentWetPeriod++; + thisDateWet = currentDay; + } + } + else + { + if (isDryNow) + { + currentDryPeriod++; + thisDateDry = currentDay; + } + else + { + currentDryPeriod = 1; + isDryNow = true; + if (currentWetPeriod > wetPeriodVal[monthOffset]) + { + wetPeriodVal[monthOffset] = currentWetPeriod; + wetPeriodTime[monthOffset] = thisDateWet; + } + currentWetPeriod = 0; + } + } + + currentDay = metoDate; + dayHighTemp = outsidetemp; + dayLowTemp = outsidetemp; + dayWindRun = 0; + totalRainfall += dayRain; + dayRain = 0; + } + + // hourly rain + /* + * need to track what the rainfall has been in the last rolling hour + * across day rollovers where the count resets + */ + AddLastHourRainEntry(entrydate, totalRainfall + dayRain); + RemoveOldRainData(entrydate); + + var rainThisHour = hourRainLog.Last().Raincounter - hourRainLog.First().Raincounter; + if (rainThisHour > highRainHourVal[monthOffset]) + { + highRainHourVal[monthOffset] = rainThisHour; + highRainHourTime[monthOffset] = entrydate; + } + + lastentrydate = entrydate; + //lastRainMidnight = rainMidnight; + } + } + catch (Exception e) + { + cumulus.LogMessage($"Error at line {linenum} of {logFile} : {e.Message}"); + cumulus.LogMessage("Please edit the file to correct the error"); + } + } + else + { + cumulus.LogDebugMessage($"GetMonthlyRecLogFile: Log file not found - {logFile}"); + } + if (filedate >= dateto) + { + finished = true; + cumulus.LogDebugMessage("GetMonthlyRecLogFile: Finished processing the log files"); + } + else + { + cumulus.LogDebugMessage($"GetMonthlyRecLogFile: Finished processing log file - {logFile}"); + filedate = filedate.AddMonths(1); + logFile = cumulus.GetLogFileName(filedate); + } + } + for (var i = 0; i < 12; i++) + { + var m = i + 1; + json += $"\"{m}-highTempValLogfile\":\"" + highTempVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highTempTimeLogfile\":\"" + highTempTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowTempValLogfile\":\"" + lowTempVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowTempTimeLogfile\":\"" + lowTempTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highDewPointValLogfile\":\"" + highDewPtVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highDewPointTimeLogfile\":\"" + highDewPtTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowDewPointValLogfile\":\"" + lowDewPtVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowDewPointTimeLogfile\":\"" + lowDewPtTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highApparentTempValLogfile\":\"" + highAppTempVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highApparentTempTimeLogfile\":\"" + highAppTempTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowApparentTempValLogfile\":\"" + lowAppTempVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowApparentTempTimeLogfile\":\"" + lowAppTempTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowWindChillValLogfile\":\"" + lowWindChillVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowWindChillTimeLogfile\":\"" + lowWindChillTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highHeatIndexValLogfile\":\"" + highHeatIndVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highHeatIndexTimeLogfile\":\"" + highHeatIndTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highMinTempValLogfile\":\"" + highMinTempVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highMinTempTimeLogfile\":\"" + highMinTempTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-lowMaxTempValLogfile\":\"" + lowMaxTempVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowMaxTempTimeLogfile\":\"" + lowMaxTempTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-highDailyTempRangeValLogfile\":\"" + highTempRangeVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-highDailyTempRangeTimeLogfile\":\"" + highTempRangeTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-lowDailyTempRangeValLogfile\":\"" + lowTempRangeVal[i].ToString(cumulus.TempFormat) + "\","; + json += $"\"{m}-lowDailyTempRangeTimeLogfile\":\"" + lowTempRangeTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-highHumidityValLogfile\":\"" + highHumVal[i].ToString(cumulus.HumFormat) + "\","; + json += $"\"{m}-highHumidityTimeLogfile\":\"" + highHumTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowHumidityValLogfile\":\"" + lowHumVal[i].ToString(cumulus.HumFormat) + "\","; + json += $"\"{m}-lowHumidityTimeLogfile\":\"" + lowHumTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highBarometerValLogfile\":\"" + highBaroVal[i].ToString(cumulus.PressFormat) + "\","; + json += $"\"{m}-highBarometerTimeLogfile\":\"" + highBaroTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-lowBarometerValLogfile\":\"" + lowBaroVal[i].ToString(cumulus.PressFormat) + "\","; + json += $"\"{m}-lowBarometerTimeLogfile\":\"" + lowBaroTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highGustValLogfile\":\"" + highGustVal[i].ToString(cumulus.WindFormat) + "\","; + json += $"\"{m}-highGustTimeLogfile\":\"" + highGustTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highWindValLogfile\":\"" + highWindVal[i].ToString(cumulus.WindFormat) + "\","; + json += $"\"{m}-highWindTimeLogfile\":\"" + highWindTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highWindRunValLogfile\":\"" + highWindRunVal[i].ToString(cumulus.WindRunFormat) + "\","; + json += $"\"{m}-highWindRunTimeLogfile\":\"" + highWindRunTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-highRainRateValLogfile\":\"" + highRainRateVal[i].ToString(cumulus.RainFormat) + "\","; + json += $"\"{m}-highRainRateTimeLogfile\":\"" + highRainRateTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highHourlyRainValLogfile\":\"" + highRainHourVal[i].ToString(cumulus.RainFormat) + "\","; + json += $"\"{m}-highHourlyRainTimeLogfile\":\"" + highRainHourTime[i].ToString(timeStampFormat) + "\","; + json += $"\"{m}-highDailyRainValLogfile\":\"" + highRainDayVal[i].ToString(cumulus.RainFormat) + "\","; + json += $"\"{m}-highDailyRainTimeLogfile\":\"" + highRainDayTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-highMonthlyRainValLogfile\":\"" + highRainMonthVal[i].ToString(cumulus.RainFormat) + "\","; + json += $"\"{m}-highMonthlyRainTimeLogfile\":\"" + highRainMonthTime[i].ToString("yyyy/MM") + "\","; + json += $"\"{m}-longestDryPeriodValLogfile\":\"" + dryPeriodVal[i].ToString() + "\","; + json += $"\"{m}-longestDryPeriodTimeLogfile\":\"" + dryPeriodTime[i].ToString(dateStampFormat) + "\","; + json += $"\"{m}-longestWetPeriodValLogfile\":\"" + wetPeriodVal[i].ToString() + "\","; + json += $"\"{m}-longestWetPeriodTimeLogfile\":\"" + wetPeriodTime[i].ToString(dateStampFormat) + "\","; + } + + json = json.Remove(json.Length - 1); + json += "}"; + + watch.Stop(); + var elapsed = watch.ElapsedMilliseconds; + cumulus.LogDebugMessage($"Monthly recs editor Logfiles load = {elapsed} ms"); + + return json; + } + + + internal string GetCurrentCond() + { + return "{\"data\":\"" + webtags.GetCurrCondText() + "\"}"; + } + + internal string EditCurrentCond(IHttpContext context) + { + var request = context.Request; + string text; + using (var reader = new StreamReader(request.InputStream, request.ContentEncoding)) + { + text = reader.ReadToEnd(); + } + + var result = SetCurrCondText(text); + + return "{\"result\":\"" + (result ? "Success" : "Failed") + "\"}"; + } + + private bool SetCurrCondText(string currCondText) + { + var fileName = cumulus.AppDir + "currentconditions.txt"; + try + { + cumulus.LogMessage("Writing current conditions to file..."); + + File.WriteAllText(fileName, currCondText); + return true; + } + catch (Exception e) + { + cumulus.LogMessage("Error writing current conditions to file - " + e.Message); + return false; + } + } + + /* + internal class JsonEditRainData + { + public double raintoday { get; set; } + public double raincounter { get; set; } + public double startofdayrain { get; set; } + public double rainmult { get; set; } + } + */ + + private void AddLastHourRainEntry(DateTime ts, double rain) + { + var lasthourrain = new LastHourRainLog(ts, rain); + + hourRainLog.Add(lasthourrain); } private class LastHourRainLog { - public DateTime timestamp; - public double raincounter; + public readonly DateTime Timestamp; + public readonly double Raincounter; public LastHourRainLog(DateTime ts, double rain) { - timestamp = ts; - raincounter = rain; + Timestamp = ts; + Raincounter = rain; } } private void RemoveOldRainData(DateTime ts) { - DateTime onehourago = ts.AddHours(-1); + var onehourago = ts.AddHours(-1); - if (HourRainLog.Count > 0) + if (hourRainLog.Count <= 0) return; + + // there are entries to consider + while ((hourRainLog.Count > 0) && (hourRainLog.First().Timestamp < onehourago)) { - // there are entries to consider - while ((HourRainLog.Count > 0) && (HourRainLog.First().timestamp < onehourago)) - { - // the oldest entry is older than 1 hour ago, delete it - HourRainLog.RemoveAt(0); - } + // the oldest entry is older than 1 hour ago, delete it + hourRainLog.RemoveAt(0); } } } diff --git a/CumulusMX/DavisWllStation.cs b/CumulusMX/DavisWllStation.cs index fb5b8dd5..3abf20f2 100644 --- a/CumulusMX/DavisWllStation.cs +++ b/CumulusMX/DavisWllStation.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Threading.Tasks; using System.IO.Ports; +using System.Linq; using System.Timers; using System.Net.Http; using System.Net.Sockets; @@ -17,11 +18,10 @@ internal class DavisWllStation : WeatherStation private string ipaddr; private int port; private int duration; - private System.Timers.Timer tmrRealtime; - private System.Timers.Timer tmrCurrent; - private ServiceBrowser serviceBrowser; - private readonly static object threadSafer = new object(); - private static SemaphoreSlim webReq = new SemaphoreSlim(1); + private readonly System.Timers.Timer tmrRealtime; + private readonly System.Timers.Timer tmrCurrent; + private readonly object threadSafer = new object(); + private static readonly SemaphoreSlim WebReq = new SemaphoreSlim(1); private bool startupDayResetIfRequired = true; public DavisWllStation(Cumulus cumulus) : base(cumulus) @@ -31,6 +31,8 @@ public DavisWllStation(Cumulus cumulus) : base(cumulus) //cumulus.UseDataLogger = false; // WLL does not provide a forecast string, so use the Cumulus forecast cumulus.UseCumulusForecast = true; + // initialise the battery status + TxBatText = "1-NA 2-NA 3-NA 4-NA 5-NA 6-NA 7-NA 8-NA"; cumulus.LogMessage("Station type = Davis WLL"); @@ -41,8 +43,8 @@ public DavisWllStation(Cumulus cumulus) : base(cumulus) // Perform zero-config // If it works - check IP address in config file and set/update if required // If it fails - just use the IP address from config file - string serviceType = "_weatherlinklive._tcp"; - serviceBrowser = new ServiceBrowser(); + const string serviceType = "_weatherlinklive._tcp"; + var serviceBrowser = new ServiceBrowser(); serviceBrowser.ServiceAdded += OnServiceAdded; serviceBrowser.ServiceRemoved += OnServiceRemoved; serviceBrowser.ServiceChanged += OnServiceChanged; @@ -65,10 +67,6 @@ public DavisWllStation(Cumulus cumulus) : base(cumulus) StartLoop(); } - // destructor - ~DavisWllStation() - { - } public override void Start() { @@ -82,14 +80,14 @@ public override void Start() // Create a realtime thread to periodically restart broadcasts GetWllRealtime(null, null); - tmrRealtime.Elapsed += new ElapsedEventHandler(GetWllRealtime); + tmrRealtime.Elapsed += GetWllRealtime; tmrRealtime.Interval = cumulus.WllBroadcastDuration * 1000; tmrRealtime.AutoReset = true; tmrRealtime.Start(); // Create a current conditions thread to poll readings once a minute GetWllCurrent(null, null); - tmrCurrent.Elapsed += new ElapsedEventHandler(GetWllCurrent); + tmrCurrent.Elapsed += GetWllCurrent; tmrCurrent.Interval = 60 * 1000; // Every 60 seconds tmrCurrent.AutoReset = true; tmrCurrent.Start(); @@ -103,16 +101,16 @@ public override void Start() port = 22222; } // Create a broadcast listener - UdpClient udpClient = new UdpClient(); + var udpClient = new UdpClient(); udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port)); var from = new IPEndPoint(0, 0); - Task t = Task.Run(() => + Task.Run(() => { - while (true) + while (!Program.exitSystem) { - var recvBuffer = udpClient.Receive(ref from); - decodeBroadcast(Encoding.UTF8.GetString(recvBuffer)); + var recvBuffer = udpClient.Receive(ref @from); + DecodeBroadcast(Encoding.UTF8.GetString(recvBuffer)); } }); @@ -147,11 +145,10 @@ public override void portDataReceived(object sender, SerialDataReceivedEventArgs private async void GetWllRealtime(object source, ElapsedEventArgs e) { - string ip; - int retry = 2; + var retry = 2; cumulus.LogDebugMessage("Lock: GetWllRealtime waiting for lock"); - webReq.Wait(); + WebReq.Wait(); cumulus.LogDebugMessage("Lock: GetWllRealtime has the lock"); using (HttpClient client = new HttpClient()) @@ -162,12 +159,14 @@ private async void GetWllRealtime(object source, ElapsedEventArgs e) // Call asynchronous network methods in a try/catch block to handle exceptions try { + string ip; + lock (threadSafer) { ip = ipaddr; } - if (CheckIPValid(ip)) + if (CheckIpValid(ip)) { var urlRealtime = "http://" + ip + "/v1/real_time?duration=" + cumulus.WllBroadcastDuration; @@ -175,9 +174,9 @@ private async void GetWllRealtime(object source, ElapsedEventArgs e) client.DefaultRequestHeaders.Add("Connection", "close"); - HttpResponseMessage response = await client.GetAsync(urlRealtime); + var response = await client.GetAsync(urlRealtime); //response.EnsureSuccessStatusCode(); - string responseBody = await response.Content.ReadAsStringAsync(); + var responseBody = await response.Content.ReadAsStringAsync(); responseBody = responseBody.TrimEnd('\r', '\n'); @@ -185,11 +184,7 @@ private async void GetWllRealtime(object source, ElapsedEventArgs e) //Console.WriteLine($" - Realtime response: {responseBody}"); var jObject = Newtonsoft.Json.Linq.JObject.Parse(responseBody); - string err = (string)jObject["error"]; - if (err == null) - { - err = "OK"; - } + var err = (string)jObject["error"] ?? "OK"; port = (int)jObject["data"]["broadcast_port"]; duration = (int)jObject["data"]["duration"]; cumulus.LogDebugMessage("GET realtime request WLL response Code: " + err + ", Port: " + (string)jObject["data"]["broadcast_port"]); @@ -222,28 +217,28 @@ private async void GetWllRealtime(object source, ElapsedEventArgs e) } while (retry > 0); cumulus.LogDebugMessage("Lock: GetWllRealtime releasing lock"); - webReq.Release(); + WebReq.Release(); } } private async void GetWllCurrent(object source, ElapsedEventArgs e) { string ip; - int retry = 2; + var retry = 2; lock (threadSafer) { ip = ipaddr; } - if (CheckIPValid(ip)) + if (CheckIpValid(ip)) { var urlCurrent = $"http://{ip}/v1/current_conditions"; cumulus.LogDebugMessage("Lock: GetWllCurrent waiting for lock"); - webReq.Wait(); + WebReq.Wait(); cumulus.LogDebugMessage("Lock: GetWllCurrent has the lock"); // The WLL will error if already responding to a request from another device, so add a retry @@ -258,15 +253,15 @@ private async void GetWllCurrent(object source, ElapsedEventArgs e) { client.DefaultRequestHeaders.Add("Connection", "close"); - HttpResponseMessage response = await client.GetAsync(urlCurrent); + var response = await client.GetAsync(urlCurrent); response.EnsureSuccessStatusCode(); - string responseBody = await response.Content.ReadAsStringAsync(); + var responseBody = await response.Content.ReadAsStringAsync(); //Console.WriteLine($" - Current conds response: {responseBody}"); // sanity check if (responseBody.StartsWith("{\"data\":{\"did\":")) { - decodeCurrent(responseBody); + DecodeCurrent(responseBody); if (startupDayResetIfRequired) { DoDayResetIfNeeded(); @@ -295,7 +290,7 @@ private async void GetWllCurrent(object source, ElapsedEventArgs e) } while (retry > 0); cumulus.LogDebugMessage("Lock: GetWllCurrent releasing lock"); - webReq.Release(); + WebReq.Release(); } else { @@ -303,10 +298,8 @@ private async void GetWllCurrent(object source, ElapsedEventArgs e) } } - private void decodeBroadcast(string broadcastJson) + private void DecodeBroadcast(string broadcastJson) { - int txid; - try { cumulus.LogDataMessage("WLL Broadcast: " + broadcastJson); @@ -319,7 +312,7 @@ private void decodeBroadcast(string broadcastJson) var dateTime = DateTime.Now; foreach (var rec in data["conditions"]) { - txid = (int)rec["txid"]; + var txid = (int)rec["txid"]; // Wind /* Available fields: @@ -330,7 +323,7 @@ private void decodeBroadcast(string broadcastJson) */ if (cumulus.WllPrimaryWind == txid) { - if (String.IsNullOrEmpty((string)rec["wind_speed_last"]) || String.IsNullOrEmpty((string)rec["wind_dir_last"])) + if (string.IsNullOrEmpty((string)rec["wind_speed_last"]) || string.IsNullOrEmpty((string)rec["wind_dir_last"])) { cumulus.LogDebugMessage($"WLL broadcast: no valid wind speed found [speed={(string)rec["wind_speed_last"]}, dir= {(string)rec["wind_dir_last"]}] on TxId {txid}"); } @@ -370,36 +363,35 @@ private void decodeBroadcast(string broadcastJson) * rec["rainfall_monthly"] * rec["rainfall_year"]) */ - if (cumulus.WllPrimaryRain == txid) + if (cumulus.WllPrimaryRain != txid) continue; + + if (string.IsNullOrEmpty((string)rec["rainfall_year"]) || string.IsNullOrEmpty((string)rec["rain_rate_last"]) || string.IsNullOrEmpty((string)rec["rain_size"])) + { + cumulus.LogDebugMessage($"WLL broadcast: no valid rainfall found [total={(string)rec["rainfall_year"]}, rate= {(string)rec["rain_rate_last"]}] on TxId {txid}"); + } + else { - if (String.IsNullOrEmpty((string)rec["rainfall_year"]) || String.IsNullOrEmpty((string)rec["rain_rate_last"]) || String.IsNullOrEmpty((string)rec["rain_size"])) + var rain = ConvertRainClicksToUser((double)rec["rainfall_year"], (int)rec["rain_size"]); + var rainrate = ConvertRainClicksToUser((double)rec["rain_rate_last"], (int)rec["rain_size"]); + + if (rainrate < 0) { - cumulus.LogDebugMessage($"WLL broadcast: no valid rainfall found [total={(string)rec["rainfall_year"]}, rate= {(string)rec["rain_rate_last"]}] on TxId {txid}"); + rainrate = 0; } - else - { - double rain = ConvertRainClicksToUser((double)rec["rainfall_year"], (int)rec["rain_size"]); - double rainrate = ConvertRainClicksToUser((double)rec["rain_rate_last"], (int)rec["rain_size"]); - - if (rainrate < 0) - { - rainrate = 0; - } - DoRain(rain, rainrate, dateTime); - } + DoRain(rain, rainrate, dateTime); } } UpdateStatusPanel(DateTime.Now); } catch (Exception exp) { - cumulus.LogDebugMessage("decodeBroadcast(): Exception Caught!"); + cumulus.LogDebugMessage("DecodeBroadcast(): Exception Caught!"); cumulus.LogDebugMessage($"Message :" + exp.Message); } } - private void decodeCurrent(string currentJson) + private void DecodeCurrent(string currentJson) { try { @@ -417,9 +409,10 @@ private void decodeCurrent(string currentJson) foreach (var rec in data["conditions"]) { - int type = (int)rec["data_structure_type"]; + var type = (int)rec["data_structure_type"]; int txid; string idx; + uint batt; switch (type) { @@ -428,6 +421,10 @@ private void decodeCurrent(string currentJson) cumulus.LogDebugMessage($"WLL current: found ISS data on TxId {txid}"); + // Battery + batt = (uint)rec["trans_battery_flag"]; + SetTxBatteryStatus(txid, batt); + // Temperature & Humidity if (cumulus.WllPrimaryTempHum == txid) { @@ -442,7 +439,7 @@ private void decodeCurrent(string currentJson) * "thsw_index": 5.5, // **(°F)** */ - if (String.IsNullOrEmpty((string)rec["temp"]) || (int)rec["temp"] == -99) + if (string.IsNullOrEmpty((string)rec["temp"]) || (int)rec["temp"] == -99) { cumulus.LogDebugMessage($"WLL current: no valid Primary temperature value found [{(string)rec["temp"]}] on TxId {txid}"); } @@ -450,7 +447,7 @@ private void decodeCurrent(string currentJson) { cumulus.LogDebugMessage($"WLL current: using temp/hum data from TxId {txid}"); - if (String.IsNullOrEmpty((string)rec["hum"])) + if (string.IsNullOrEmpty((string)rec["hum"])) { cumulus.LogDebugMessage($"WLL current: no valid Primary humidity value found [{(string)rec["hum"]}] on TxId {txid}"); } @@ -461,7 +458,7 @@ private void decodeCurrent(string currentJson) DoOutdoorTemp(ConvertTempFToUser((double)rec["temp"]), dateTime); - if (String.IsNullOrEmpty((string)rec["dew_point"])) + if (string.IsNullOrEmpty((string)rec["dew_point"])) { cumulus.LogDebugMessage($"WLL current: no valid dewpoint value found [{(string)rec["dew_point"]}] on TxId {txid}"); } @@ -473,7 +470,7 @@ private void decodeCurrent(string currentJson) if (!cumulus.CalculatedWC) { // use wind chill from WLL - if (String.IsNullOrEmpty((string)rec["wind_chill"])) + if (string.IsNullOrEmpty((string)rec["wind_chill"])) { cumulus.LogDebugMessage($"WLL current: no valid wind chill value found [{(string)rec["wind_chill"]}] on TxId {txid}"); } @@ -489,31 +486,29 @@ private void decodeCurrent(string currentJson) } else { // Check for Extra temperature/humidity settings - for (int tempTxId = 1; tempTxId <= 8; tempTxId++) + for (var tempTxId = 1; tempTxId <= 8; tempTxId++) { - if (cumulus.WllExtraTempTx[tempTxId - 1] == txid) + if (cumulus.WllExtraTempTx[tempTxId - 1] != txid) continue; + + if (string.IsNullOrEmpty((string)rec["temp"]) || (int)rec["temp"] == -99) { - if (String.IsNullOrEmpty((string)rec["temp"]) || (int)rec["temp"] == -99) + cumulus.LogDebugMessage($"WLL current: no valid Extra temperature value found [{(string)rec["temp"]}] on TxId {txid}"); + } + else + { + cumulus.LogDebugMessage($"WLL current: using extra temp data from TxId {txid}"); + + DoExtraTemp(ConvertTempFToUser((double)rec["temp"]), tempTxId); + + if (!cumulus.WllExtraHumTx[tempTxId - 1]) continue; + + if (string.IsNullOrEmpty((string)rec["hum"])) { - cumulus.LogDebugMessage($"WLL current: no valid Extra temperature value found [{(string)rec["temp"]}] on TxId {txid}"); + cumulus.LogDebugMessage($"WLL current: no valid Extra humidity value found [{(string)rec["hum"]}] on TxId {txid}"); } else { - cumulus.LogDebugMessage($"WLL current: using extra temp data from TxId {txid}"); - - DoExtraTemp(ConvertTempFToUser((double)rec["temp"]), tempTxId); - - if (cumulus.WllExtraHumTx[tempTxId - 1]) - { - if (String.IsNullOrEmpty((string)rec["hum"])) - { - cumulus.LogDebugMessage($"WLL current: no valid Extra humidity value found [{(string)rec["hum"]}] on TxId {txid}"); - } - else - { - DoExtraHum((int)rec["hum"], tempTxId); - } - } + DoExtraHum((int)rec["hum"], tempTxId); } } } @@ -538,7 +533,7 @@ private void decodeCurrent(string currentJson) * "wind_dir_at_hi_speed_last_10_min":0.0, // gust wind direction over last 10 min **(°degree)** */ - if (String.IsNullOrEmpty((string)rec["wind_speed_last"])) + if (string.IsNullOrEmpty((string)rec["wind_speed_last"])) { cumulus.LogDebugMessage($"WLL current: no wind_speed_last value found [{(string)rec["wind_speed_last"]}] on TxId {txid}"); } @@ -548,7 +543,7 @@ private void decodeCurrent(string currentJson) DoWind((double)rec["wind_speed_last"], (int)rec["wind_dir_last"], (double)rec["wind_speed_avg_last_10_min"], dateTime); - if (String.IsNullOrEmpty((string)rec["wind_speed_avg_last_10_min"])) + if (string.IsNullOrEmpty((string)rec["wind_speed_avg_last_10_min"])) { cumulus.LogDebugMessage("WLL current: no wind speed 10 min average value found [avg=" + (string)rec["wind_speed_avg_last_10_min"] + "] on TxId " + txid); @@ -562,8 +557,8 @@ private void decodeCurrent(string currentJson) { // See if the current speed is higher than the current 10-min max // We can then update the figure before the next LOOP2 packet is read - if (String.IsNullOrEmpty((string)rec["wind_speed_hi_last_10_min"]) || - String.IsNullOrEmpty((string)rec["wind_dir_at_hi_speed_last_10_min"])) + if (string.IsNullOrEmpty((string)rec["wind_speed_hi_last_10_min"]) || + string.IsNullOrEmpty((string)rec["wind_dir_at_hi_speed_last_10_min"])) { cumulus.LogDebugMessage("WLL current: no wind speed 10 min high values found [speed=" + (string)rec["wind_speed_hi_last_10_min"] + @@ -623,9 +618,9 @@ private void decodeCurrent(string currentJson) //DoRain(rain, rainrate, dateTime); - if (String.IsNullOrEmpty((string)rec["rain_storm"]) || - String.IsNullOrEmpty((string)rec["rain_storm_start_at"]) || - String.IsNullOrEmpty((string)rec["rain_size"])) + if (string.IsNullOrEmpty((string)rec["rain_storm"]) || + string.IsNullOrEmpty((string)rec["rain_storm_start_at"]) || + string.IsNullOrEmpty((string)rec["rain_size"])) { cumulus.LogDebugMessage("WLL current: no rain storm values found [speed=" + (string)rec["rain_storm"] + @@ -643,7 +638,7 @@ private void decodeCurrent(string currentJson) if (cumulus.WllPrimaryUV == txid) { - if (String.IsNullOrEmpty((string)rec["uv_index"])) + if (string.IsNullOrEmpty((string)rec["uv_index"])) { cumulus.LogDebugMessage($"WLL current: no valid UV value found [{(string)rec["uv_index"]}] on TxId {txid}"); } @@ -656,7 +651,7 @@ private void decodeCurrent(string currentJson) if (cumulus.WllPrimarySolar == txid) { - if (String.IsNullOrEmpty((string)rec["solar_rad"])) + if (string.IsNullOrEmpty((string)rec["solar_rad"])) { cumulus.LogDebugMessage($"WLL current: no valid Solar value found [{(string)rec["solar_rad"]}] on TxId {txid}"); } @@ -668,166 +663,171 @@ private void decodeCurrent(string currentJson) } break; - case 2: // Leaf/Soil Mositure - /* - * Available fields - * "temp_1":null, // most recent valid soil temp slot 1 **(°F)** - * "temp_2":null, // most recent valid soil temp slot 2 **(°F)** - * "temp_3":null, // most recent valid soil temp slot 3 **(°F)** - * "temp_4":null, // most recent valid soil temp slot 4 **(°F)** - * "moist_soil_1":null, // most recent valid soil moisture slot 1 **(|cb|)** - * "moist_soil_2":null, // most recent valid soil moisture slot 2 **(|cb|)** - * "moist_soil_3":null, // most recent valid soil moisture slot 3 **(|cb|)** - * "moist_soil_4":null, // most recent valid soil moisture slot 4 **(|cb|)** - * "wet_leaf_1":null, // most recent valid leaf wetness slot 1 **(no unit)** - * "wet_leaf_2":null, // most recent valid leaf wetness slot 2 **(no unit)** - * "rx_state":null, // configured radio receiver state **(no unit)** - * "trans_battery_flag":null // transmitter battery status flag **(no unit)** - */ - txid = (int)rec["txid"]; + case 2: // Leaf/Soil Moisture + /* + * Available fields + * "temp_1":null, // most recent valid soil temp slot 1 **(°F)** + * "temp_2":null, // most recent valid soil temp slot 2 **(°F)** + * "temp_3":null, // most recent valid soil temp slot 3 **(°F)** + * "temp_4":null, // most recent valid soil temp slot 4 **(°F)** + * "moist_soil_1":null, // most recent valid soil moisture slot 1 **(|cb|)** + * "moist_soil_2":null, // most recent valid soil moisture slot 2 **(|cb|)** + * "moist_soil_3":null, // most recent valid soil moisture slot 3 **(|cb|)** + * "moist_soil_4":null, // most recent valid soil moisture slot 4 **(|cb|)** + * "wet_leaf_1":null, // most recent valid leaf wetness slot 1 **(no unit)** + * "wet_leaf_2":null, // most recent valid leaf wetness slot 2 **(no unit)** + * "rx_state":null, // configured radio receiver state **(no unit)** + * "trans_battery_flag":null // transmitter battery status flag **(no unit)** + */ + + txid = (int)rec["txid"]; - cumulus.LogDebugMessage($"WLL current: found Leaf/Soil data on TxId {txid}"); + cumulus.LogDebugMessage($"WLL current: found Leaf/Soil data on TxId {txid}"); - // Leaf wetness - if (cumulus.WllExtraLeafTx1 == txid) + // Battery + batt = (uint)rec["trans_battery_flag"]; + SetTxBatteryStatus(txid, batt); + + // Leaf wetness + if (cumulus.WllExtraLeafTx1 == txid) + { + idx = "wet_leaf_" + cumulus.WllExtraLeafIdx1; + if (string.IsNullOrEmpty((string)rec[idx])) { - idx = "wet_leaf_" + cumulus.WllExtraLeafIdx1; - if (String.IsNullOrEmpty((string)rec[idx])) - { - cumulus.LogDebugMessage($"WLL current: no valid leaf wetness #{cumulus.WllExtraLeafIdx1} found [{(string)rec[idx]}] on TxId {txid}"); - } - else - { - DoLeafWetness((double)rec[idx], 1); - } + cumulus.LogDebugMessage($"WLL current: no valid leaf wetness #{cumulus.WllExtraLeafIdx1} found [{(string)rec[idx]}] on TxId {txid}"); } - if (cumulus.WllExtraLeafTx2 == txid) + else { - idx = "wet_leaf_" + cumulus.WllExtraLeafIdx2; - if (String.IsNullOrEmpty((string)rec[idx])) - { - cumulus.LogDebugMessage($"WLL current: no valid leaf wetness #{cumulus.WllExtraLeafIdx2} found [{(string)rec[idx]}] on TxId {txid}"); - } - else - { - DoLeafWetness((double)rec[idx], 2); - } + DoLeafWetness((double)rec[idx], 1); + } + } + if (cumulus.WllExtraLeafTx2 == txid) + { + idx = "wet_leaf_" + cumulus.WllExtraLeafIdx2; + if (string.IsNullOrEmpty((string)rec[idx])) + { + cumulus.LogDebugMessage($"WLL current: no valid leaf wetness #{cumulus.WllExtraLeafIdx2} found [{(string)rec[idx]}] on TxId {txid}"); + } + else + { + DoLeafWetness((double)rec[idx], 2); } + } - // Soil moisture - if (cumulus.WllExtraSoilMoistureTx1 == txid) + // Soil moisture + if (cumulus.WllExtraSoilMoistureTx1 == txid) + { + idx = "moist_soil_" + cumulus.WllExtraSoilMoistureIdx1; + if (string.IsNullOrEmpty((string)rec[idx])) { - idx = "moist_soil_" + cumulus.WllExtraSoilMoistureIdx1; - if (String.IsNullOrEmpty((string)rec[idx])) - { - cumulus.LogDebugMessage($"WLL current: no valid soil moisture #{cumulus.WllExtraSoilMoistureIdx1} found [{(string)rec[idx]}] on TxId {txid}"); - } - else - { - DoSoilMoisture((double)rec[idx], 1); - } + cumulus.LogDebugMessage($"WLL current: no valid soil moisture #{cumulus.WllExtraSoilMoistureIdx1} found [{(string)rec[idx]}] on TxId {txid}"); } - if (cumulus.WllExtraSoilMoistureTx2 == txid) + else { - idx = "moist_soil_" + cumulus.WllExtraSoilMoistureIdx2; - if (String.IsNullOrEmpty((string)rec[idx])) - { - cumulus.LogDebugMessage($"WLL current: no valid soil moisture #{cumulus.WllExtraSoilMoistureIdx2} found [{(string)rec[idx]}] on TxId {txid}"); - } - else - { - DoSoilMoisture((double)rec[idx], 2); - } + DoSoilMoisture((double)rec[idx], 1); } - if (cumulus.WllExtraSoilMoistureTx3 == txid) + } + if (cumulus.WllExtraSoilMoistureTx2 == txid) + { + idx = "moist_soil_" + cumulus.WllExtraSoilMoistureIdx2; + if (string.IsNullOrEmpty((string)rec[idx])) { - idx = "moist_soil_" + cumulus.WllExtraSoilMoistureIdx3; - if (String.IsNullOrEmpty((string)rec[idx])) - { - cumulus.LogDebugMessage($"WLL current: no valid soil moisture #{cumulus.WllExtraSoilMoistureIdx3} found [{(string)rec[idx]}] on TxId {txid}"); - } - else - { - DoSoilMoisture((double)rec[idx], 3); - } + cumulus.LogDebugMessage($"WLL current: no valid soil moisture #{cumulus.WllExtraSoilMoistureIdx2} found [{(string)rec[idx]}] on TxId {txid}"); } - if (cumulus.WllExtraSoilMoistureTx4 == txid) + else { - idx = "moist_soil_" + cumulus.WllExtraSoilMoistureIdx4; - if (String.IsNullOrEmpty((string)rec[idx])) - { - cumulus.LogDebugMessage($"WLL current: no valid soil moisture #{cumulus.WllExtraSoilMoistureIdx4} found [{(string)rec[idx]}] on TxId {txid}"); - } - else - { - DoSoilMoisture((double)rec[idx], 4); - } + DoSoilMoisture((double)rec[idx], 2); + } + } + if (cumulus.WllExtraSoilMoistureTx3 == txid) + { + idx = "moist_soil_" + cumulus.WllExtraSoilMoistureIdx3; + if (string.IsNullOrEmpty((string)rec[idx])) + { + cumulus.LogDebugMessage($"WLL current: no valid soil moisture #{cumulus.WllExtraSoilMoistureIdx3} found [{(string)rec[idx]}] on TxId {txid}"); + } + else + { + DoSoilMoisture((double)rec[idx], 3); + } + } + if (cumulus.WllExtraSoilMoistureTx4 == txid) + { + idx = "moist_soil_" + cumulus.WllExtraSoilMoistureIdx4; + if (string.IsNullOrEmpty((string)rec[idx])) + { + cumulus.LogDebugMessage($"WLL current: no valid soil moisture #{cumulus.WllExtraSoilMoistureIdx4} found [{(string)rec[idx]}] on TxId {txid}"); + } + else + { + DoSoilMoisture((double)rec[idx], 4); } + } - // SoilTemperature - if (cumulus.WllExtraSoilTempTx1 == txid) + // SoilTemperature + if (cumulus.WllExtraSoilTempTx1 == txid) + { + idx = "temp_" + cumulus.WllExtraSoilTempIdx1; + if (string.IsNullOrEmpty((string)rec[idx])) { - idx = "temp_" + cumulus.WllExtraSoilTempIdx1; - if (String.IsNullOrEmpty((string)rec[idx])) - { - cumulus.LogDebugMessage($"WLL current: no valid extra soil temp #{cumulus.WllExtraSoilTempIdx1} found [{(string)rec[idx]}] on TxId {txid}"); - } - else - { - DoSoilTemp(ConvertTempFToUser((double)rec[idx]), 1); - } + cumulus.LogDebugMessage($"WLL current: no valid extra soil temp #{cumulus.WllExtraSoilTempIdx1} found [{(string)rec[idx]}] on TxId {txid}"); } - if (cumulus.WllExtraSoilTempTx2 == txid) + else { - idx = "temp_" + cumulus.WllExtraSoilTempIdx2; - if (String.IsNullOrEmpty((string)rec[idx])) - { - cumulus.LogDebugMessage($"WLL current: no valid extra soil temp #{cumulus.WllExtraSoilTempIdx2} found [{(string)rec[idx]}] on TxId {txid}"); - } - else - { - DoSoilTemp(ConvertTempFToUser((double)rec[idx]), 2); - } + DoSoilTemp(ConvertTempFToUser((double)rec[idx]), 1); } - if (cumulus.WllExtraSoilTempTx3 == txid) + } + if (cumulus.WllExtraSoilTempTx2 == txid) + { + idx = "temp_" + cumulus.WllExtraSoilTempIdx2; + if (string.IsNullOrEmpty((string)rec[idx])) { - idx = "temp_" + cumulus.WllExtraSoilTempIdx3; - if (String.IsNullOrEmpty((string)rec[idx])) - { - cumulus.LogDebugMessage($"WLL current: no valid extra soil temp #{cumulus.WllExtraSoilTempIdx3} found [{(string)rec[idx]}] on TxId {txid}"); - } - else - { - DoSoilTemp(ConvertTempFToUser((double)rec[idx]), 3); - } + cumulus.LogDebugMessage($"WLL current: no valid extra soil temp #{cumulus.WllExtraSoilTempIdx2} found [{(string)rec[idx]}] on TxId {txid}"); } - if (cumulus.WllExtraSoilTempTx4 == txid) + else { - idx = "temp_" + cumulus.WllExtraSoilTempIdx4; - if (String.IsNullOrEmpty((string)rec[idx])) - { - cumulus.LogDebugMessage($"WLL current: no valid extra soil temp #{cumulus.WllExtraSoilTempIdx4} found [{(string)rec[idx]}] on TxId {txid}"); - } - else - { - DoSoilTemp(ConvertTempFToUser((double)rec[idx]), 4); - } + DoSoilTemp(ConvertTempFToUser((double)rec[idx]), 2); + } + } + if (cumulus.WllExtraSoilTempTx3 == txid) + { + idx = "temp_" + cumulus.WllExtraSoilTempIdx3; + if (string.IsNullOrEmpty((string)rec[idx])) + { + cumulus.LogDebugMessage($"WLL current: no valid extra soil temp #{cumulus.WllExtraSoilTempIdx3} found [{(string)rec[idx]}] on TxId {txid}"); + } + else + { + DoSoilTemp(ConvertTempFToUser((double)rec[idx]), 3); + } + } + if (cumulus.WllExtraSoilTempTx4 == txid) + { + idx = "temp_" + cumulus.WllExtraSoilTempIdx4; + if (string.IsNullOrEmpty((string)rec[idx])) + { + cumulus.LogDebugMessage($"WLL current: no valid extra soil temp #{cumulus.WllExtraSoilTempIdx4} found [{(string)rec[idx]}] on TxId {txid}"); + } + else + { + DoSoilTemp(ConvertTempFToUser((double)rec[idx]), 4); } + } - // TODO: Extra Humidity? No type for this on WLL - break; + // TODO: Extra Humidity? No type for this on WLL + break; - case 3: // Barometer - /* - * Available fields: - * rec["bar_sea_level"] - * rec["bar_absolute"] - * rec["bar_trend"] - */ + case 3: // Barometer + /* + * Available fields: + * rec["bar_sea_level"] + * rec["bar_absolute"] + * rec["bar_trend"] + */ cumulus.LogDebugMessage("WLL current: found Baro data"); - if (String.IsNullOrEmpty((string)rec["bar_sea_level"])) + if (string.IsNullOrEmpty((string)rec["bar_sea_level"])) { cumulus.LogDebugMessage($"WLL current: no valid baro reading found [{(string)rec["bar_sea_level"]}]"); } @@ -850,7 +850,7 @@ private void decodeCurrent(string currentJson) cumulus.LogDebugMessage("WLL current: found Indoor temp/hum data"); - if (String.IsNullOrEmpty((string)rec["temp_in"])) + if (string.IsNullOrEmpty((string)rec["temp_in"])) { cumulus.LogDebugMessage($"WLL current: no valid temp-in reading found [{(string)rec["temp_in"]}]"); } @@ -859,7 +859,7 @@ private void decodeCurrent(string currentJson) DoIndoorTemp(ConvertTempFToUser((double)rec["temp_in"])); } - if (String.IsNullOrEmpty((string)rec["hum_in"])) + if (string.IsNullOrEmpty((string)rec["hum_in"])) { cumulus.LogDebugMessage($"WLL current: no valid humidity-in reading found [{(string)rec["hum_in"]}]"); } @@ -869,6 +869,10 @@ private void decodeCurrent(string currentJson) } break; + + default: + cumulus.LogDebugMessage($"WLL current: found an unknown tramsmitter type [{type}]!"); + break; } DoForecast("", false); @@ -901,7 +905,7 @@ private void decodeCurrent(string currentJson) } } - private DateTime FromUnixTime(long unixTime) + private static DateTime FromUnixTime(long unixTime) { // WWL uses UTC ticks, convert to local time var utcTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(unixTime); @@ -965,15 +969,15 @@ private void PrintService(char startChar, ServiceAnnouncement service) lock (threadSafer) { ipaddr = service.Addresses[0].ToString(); - } - if (cumulus.VP2IPAddr != ipaddr) - { - cumulus.LogMessage("WLL IP address changed from " + cumulus.VP2IPAddr + " to " + ipaddr); - cumulus.VP2IPAddr = ipaddr; - } - else - { - cumulus.LogMessage("WLL found at IP address " + ipaddr); + if (cumulus.VP2IPAddr != ipaddr) + { + cumulus.LogMessage("WLL IP address changed from " + cumulus.VP2IPAddr + " to " + ipaddr); + cumulus.VP2IPAddr = ipaddr; + } + else + { + cumulus.LogMessage("WLL found at IP address " + ipaddr); + } } } @@ -1019,23 +1023,39 @@ internal double ConvertRainClicksToUser(double clicks, int size) } } - private Boolean CheckIPValid(String strIP) + private static bool CheckIpValid(string strIp) { - if (String.IsNullOrEmpty(strIP)) + if (string.IsNullOrEmpty(strIp)) return false; // Split string by ".", check that array length is 4 - string[] arrOctets = strIP.Split('.'); + var arrOctets = strIp.Split('.'); if (arrOctets.Length != 4) return false; //Check each substring checking that parses to byte - byte obyte = 0; - foreach (string strOctet in arrOctets) - if (!byte.TryParse(strOctet, out obyte)) - return false; - - return true; + return arrOctets.All(strOctet => byte.TryParse(strOctet, out _)); } + private void SetTxBatteryStatus(int txId, uint status) + { + // Split the string + var delimiters = new[] { ' ', '-' }; + var sl = TxBatText.Split(delimiters); + + TxBatText = ""; + for (var i = 1; i <= 8; i++) + { + TxBatText += i; + if (i == txId) + { + TxBatText += (status == 0 ? "-OK " : "-LOW "); + } + else + { + TxBatText += "-" + sl[(i-1) * 2 + 1] + " "; + } + } + TxBatText = TxBatText.Trim(); + } } } \ No newline at end of file diff --git a/CumulusMX/GW1000Station.cs b/CumulusMX/GW1000Station.cs index 43ef4e1d..2af8b94f 100644 --- a/CumulusMX/GW1000Station.cs +++ b/CumulusMX/GW1000Station.cs @@ -1,12 +1,10 @@ using System; using System.ComponentModel; using System.IO.Ports; -using System.IO; using System.Net.Sockets; using System.Text; using System.Threading; using System.Runtime.InteropServices; -using System.Runtime.Serialization.Formatters.Binary; namespace CumulusMX @@ -14,9 +12,9 @@ namespace CumulusMX internal class GW1000Station : WeatherStation { private readonly string ipaddr; - private static int port = 45000; + private const int AT_port = 45000; private int lastMinute; - bool tenMinuteChanged = true; + private bool tenMinuteChanged = true; private TcpClient socket; private bool connectedOK = false; @@ -120,6 +118,7 @@ private enum CommandRespSize : int ch8 = 1 << 7 } + /* private enum _wh41_ch : UInt16 { ch1 = 15 << 0, @@ -127,8 +126,9 @@ private enum _wh41_ch : UInt16 ch3 = 15 << 8, ch4 = 15 << 12 } + */ - [Flags] private enum _wh51_ch : UInt16 + [Flags] private enum _wh51_ch : UInt32 { ch1 = 1 << 0, ch2 = 1 << 1, @@ -203,7 +203,7 @@ public GW1000Station(Cumulus cumulus) : base(cumulus) ipaddr = cumulus.Gw1000IpAddress; - cumulus.LogMessage("IP address = " + ipaddr + " Port = " + port); + cumulus.LogMessage("IP address = " + ipaddr + " Port = " + AT_port); socket = OpenTcpPort(); connectedOK = socket != null; @@ -222,10 +222,10 @@ public GW1000Station(Cumulus cumulus) : base(cumulus) if (connectedOK) { // Get the firmware version as check we are communicating - GW1000FirmwareVersion = getFirmwareVersion(); + GW1000FirmwareVersion = GetFirmwareVersion(); cumulus.LogMessage($"GW1000 firmware version: {GW1000FirmwareVersion}"); - getSensorIds(); + GetSensorIds(); } timerStartNeeded = true; @@ -255,7 +255,7 @@ private TcpClient OpenTcpPort() cumulus.LogDebugMessage("GW1000 Connect attempt " + attempt); try { - client = new TcpClient(ipaddr, port); + client = new TcpClient(ipaddr, AT_port); if (!client.Connected) { @@ -271,7 +271,7 @@ private TcpClient OpenTcpPort() } // Set the timeout of the underlying stream - if (!(client == null)) + if (client != null) { client.GetStream().ReadTimeout = 2500; cumulus.LogDebugMessage("GW1000 reconnected"); @@ -327,8 +327,11 @@ public override void Start() } finally { - socket.GetStream().WriteByte(10); - socket.Close(); + if (socket != null) + { + socket.GetStream().WriteByte(10); + socket.Close(); + } } } @@ -361,9 +364,9 @@ private void bw_DoStart(object sender, DoWorkEventArgs e) } - private string getFirmwareVersion() + private string GetFirmwareVersion() { - string response = "???"; + var response = "???"; cumulus.LogMessage("Reading firmware version"); var data = DoCommand((byte)Commands.CMD_READ_FIRMWARE_VERSION); @@ -374,7 +377,7 @@ private string getFirmwareVersion() return response; } - private bool getSensorIds() + private bool GetSensorIds() { cumulus.LogMessage("Reading sensor ids"); @@ -398,7 +401,7 @@ private bool getSensorIds() { for (int i = 4; i < data[3]; i += 7) { - printSensorInfo(data, i); + PrintSensorInfo(data, i); } return true; @@ -409,26 +412,26 @@ private bool getSensorIds() } } - private void printSensorInfo(byte[] data, int idx) + private void PrintSensorInfo(byte[] data, int idx) { - var id = convertBigEndianUInt32(data, idx + 1); + var id = ConvertBigEndianUInt32(data, idx + 1); + var type = Enum.GetName(typeof(SensorIds), data[idx]); - string type = Enum.GetName(typeof(SensorIds), data[idx]); if (string.IsNullOrEmpty(type)) { type = $"unknown type = {id}"; } - if (id == 0xFFFFFFFE) - { - cumulus.LogDebugMessage($" - {type} sensor = disabled"); - } - else if (id == 0xFFFFFFFF) - { - cumulus.LogDebugMessage($" - {type} sensor = registering"); - } - else + switch (id) { - cumulus.LogDebugMessage($" - {type} sensor id = {id} signal = {data[idx+5]} battery = {data[idx+6]}"); + case 0xFFFFFFFE: + cumulus.LogDebugMessage($" - {type} sensor = disabled"); + break; + case 0xFFFFFFFF: + cumulus.LogDebugMessage($" - {type} sensor = registering"); + break; + default: + cumulus.LogDebugMessage($" - {type} sensor id = {id} signal = {data[idx+5]} battery = {data[idx+6]}"); + break; } } @@ -467,38 +470,38 @@ public void GetLiveData() Int16 tempInt16; UInt16 tempUint16; UInt32 tempUint32; - int idx = 5; + var idx = 5; var dateTime = DateTime.Now; - ushort size = convertBigEndianUInt16(data, 3); - int chan = 0; + var size = ConvertBigEndianUInt16(data, 3); + int chan; - double windSpeedLast, rainRateLast, rainLast, gustLast; - windSpeedLast = rainRateLast = rainLast = gustLast = 0; - int windDirLast = 0; + double rainRateLast, rainLast, gustLast; + var windSpeedLast = rainRateLast = rainLast = gustLast = 0; + var windDirLast = 0; do { switch (data[idx++]) { case 0x01: //Indoor Temperature (℃) - tempInt16 = convertBigEndianInt16(data, idx); + tempInt16 = ConvertBigEndianInt16(data, idx); DoIndoorTemp(ConvertTempCToUser(tempInt16 / 10.0)); idx += 2; break; case 0x02: //Outdoor Temperature (℃) - tempInt16 = convertBigEndianInt16(data, idx); + tempInt16 = ConvertBigEndianInt16(data, idx); DoOutdoorTemp(ConvertTempCToUser(tempInt16 / 10.0), dateTime); idx += 2; break; case 0x03: //Dew point (℃) - tempInt16 = convertBigEndianInt16(data, idx); + tempInt16 = ConvertBigEndianInt16(data, idx); DoOutdoorDewpoint(ConvertTempCToUser(tempInt16 / 10.0), dateTime); idx += 2; break; case 0x04: //Wind chill (℃) if (!cumulus.CalculatedWC) { - tempInt16 = convertBigEndianInt16(data, idx); + tempInt16 = ConvertBigEndianInt16(data, idx); DoWindChill(ConvertTempFToUser(tempInt16 / 10.0), dateTime); } idx += 2; @@ -519,28 +522,28 @@ public void GetLiveData() idx += 2; break; case 0x09: //Relative Barometric (hpa) - tempUint16 = convertBigEndianUInt16(data, idx); + tempUint16 = ConvertBigEndianUInt16(data, idx); DoPressure(ConvertPressMBToUser(tempUint16 / 10.0), dateTime); DoPressTrend("Pressure trend"); idx += 2; break; case 0x0A: //Wind Direction (360°) - windDirLast = convertBigEndianUInt16(data, idx); + windDirLast = ConvertBigEndianUInt16(data, idx); idx += 2; break; case 0x0B: //Wind Speed (m/s) - windSpeedLast = ConvertWindMSToUser(convertBigEndianUInt16(data, idx) / 10.0); + windSpeedLast = ConvertWindMSToUser(ConvertBigEndianUInt16(data, idx) / 10.0); idx += 2; break; case 0x0C: // Gust speed (m/s) - gustLast = ConvertWindMSToUser(convertBigEndianUInt16(data, idx) / 10.0); + gustLast = ConvertWindMSToUser(ConvertBigEndianUInt16(data, idx) / 10.0); idx += 2; break; case 0x0D: //Rain Event (mm) idx += 2; break; case 0x0E: //Rain Rate (mm/h) - rainRateLast = ConvertRainMMToUser(convertBigEndianUInt16(data, idx) / 10.0); + rainRateLast = ConvertRainMMToUser(ConvertBigEndianUInt16(data, idx) / 10.0); idx += 2; break; case 0x0F: //Rain hour (mm) @@ -556,7 +559,7 @@ public void GetLiveData() idx += 4; break; case 0x13: //Rain Year (mm) - rainLast = ConvertRainMMToUser(convertBigEndianUInt32(data, idx) / 10.0); + rainLast = ConvertRainMMToUser(ConvertBigEndianUInt32(data, idx) / 10.0); idx += 4; break; case 0x14: //Rain Totals (mm) @@ -564,7 +567,7 @@ public void GetLiveData() break; case 0x15: //Light (lux) // convert LUX to W/m2 - approximately! - tempUint32 = (UInt32)(convertBigEndianUInt32(data, idx) * cumulus.LuxToWM2 / 10.0); + tempUint32 = (UInt32)(ConvertBigEndianUInt32(data, idx) * cumulus.LuxToWM2 / 10.0); DoSolarRad((int)tempUint32, dateTime); idx += 4; break; @@ -590,7 +593,7 @@ public void GetLiveData() case 0x20: //Temperature 7(℃) case 0x21: //Temperature 8(℃) chan = data[idx - 1] - 0x1A + 1; - tempInt16 = convertBigEndianInt16(data, idx); + tempInt16 = ConvertBigEndianInt16(data, idx); DoExtraTemp(ConvertTempCToUser(tempInt16 / 10.0), chan); idx += 2; break; @@ -624,7 +627,7 @@ public void GetLiveData() case 0x49: //Soil Temperature16 (℃) chan = data[idx - 1] - 0x2B + 1; chan += (chan - 1); - tempInt16 = convertBigEndianInt16(data, idx); + tempInt16 = ConvertBigEndianInt16(data, idx); DoSoilTemp(ConvertTempCToUser(tempInt16 / 10.0), chan); idx += 2; break; @@ -647,7 +650,7 @@ public void GetLiveData() // figure out the channel number chan = data[idx - 1] - 0x2C + 1; chan += (chan - 1); - DoSoilMoisture((double)data[idx], chan); + DoSoilMoisture(data[idx], chan); idx += 1; break; case 0x4C: //All sensor lowbatt 16 char @@ -660,7 +663,7 @@ public void GetLiveData() idx += 16; break; case 0x2A: //PM2.5 Air Quality Sensor(μg/m3) - tempUint16 = convertBigEndianUInt16(data, idx); + tempUint16 = ConvertBigEndianUInt16(data, idx); DoAirQuality(tempUint16 / 10.0, 1); idx += 2; break; @@ -669,7 +672,7 @@ public void GetLiveData() case 0x4F: //for pm25_ch3 case 0x50: //for pm25_ch4 chan = data[idx - 1] - 0x4D + 1; - tempUint16 = convertBigEndianUInt16(data, idx); + tempUint16 = ConvertBigEndianUInt16(data, idx); DoAirQualityAvg(tempUint16 / 10.0, chan); idx += 2; break; @@ -677,7 +680,7 @@ public void GetLiveData() case 0x52: //PM2.5 ch_3 Air Quality Sensor(μg/m3) case 0x53: //PM2.5 ch_4 Air Quality Sensor(μg/m3) chan = data[idx - 1] - 0x51 + 2; - tempUint16 = convertBigEndianUInt16(data, idx); + tempUint16 = ConvertBigEndianUInt16(data, idx); DoAirQuality(tempUint16 / 10.0, chan); idx += 2; break; @@ -695,15 +698,15 @@ public void GetLiveData() idx += 1; break; case 0x62: //Lightning time (UTC) - tempUint32 = convertBigEndianUInt32(data, idx); - System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc); + tempUint32 = ConvertBigEndianUInt32(data, idx); + var dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); dtDateTime = dtDateTime.AddSeconds(tempUint32).ToLocalTime(); //cumulus.LogDebugMessage($"Lightning time={dtDateTime}"); LightningTime = dtDateTime; idx += 4; break; case 0x63: //Lightning strikes today - tempUint32 = convertBigEndianUInt32(data, idx); + tempUint32 = ConvertBigEndianUInt32(data, idx); cumulus.LogDebugMessage($"Lightning power={tempUint32}"); LightningStrikesToday = (int)tempUint32; idx += 4; @@ -769,22 +772,22 @@ public override void portDataReceived(object sender, SerialDataReceivedEventArgs { } - private byte[] DoCommand(byte Command) + private byte[] DoCommand(byte command) { - byte[] buffer = new byte[2028]; + var buffer = new byte[2028]; byte[] data; var bytesRead = 0; - var cmdName = Enum.GetName(typeof(Commands), Command); + var cmdName = Enum.GetName(typeof(Commands), command); - CommandPayload payload = new CommandPayload(Command); - CommTimer tmrComm = new CommTimer(); + var payload = new CommandPayload(command); + var tmrComm = new CommTimer(); - byte[] bytes = payload.Serialise(); + var bytes = payload.Serialise(); try { - NetworkStream stream = socket.GetStream(); + var stream = socket.GetStream(); stream.Write(bytes, 0, bytes.Length); tmrComm.Start(1000); @@ -809,7 +812,7 @@ private byte[] DoCommand(byte Command) } } // Check the response is to our command and checksum is OK - if (buffer[2] != Command || !ChecksumOK(buffer, (int)Enum.Parse(typeof(CommandRespSize), cmdName))) + if (buffer[2] != command || !ChecksumOK(buffer, (int)Enum.Parse(typeof(CommandRespSize), cmdName))) { cumulus.LogMessage($"DoCommand({cmdName}): Invalid response"); cumulus.LogDataMessage("Received 0x" + BitConverter.ToString(buffer, 0, bytesRead - 1)); @@ -844,58 +847,58 @@ private void DoBatteryStatus(byte[] data, int index) BatteryStatus status = (BatteryStatus)RawDeserialize(data, index, typeof(BatteryStatus)); cumulus.LogDebugMessage("battery status..."); - var str = "singles> wh24=" + testBattery1(status.single, (byte)_sig_sen.wh24); - str += " wh25=" + testBattery1(status.single, (byte)_sig_sen.wh25); - str += " wh26=" + testBattery1(status.single, (byte)_sig_sen.wh26); - str += " wh40=" + testBattery1(status.single, (byte)_sig_sen.wh40); + var str = "singles> wh24=" + TestBattery1(status.single, (byte)_sig_sen.wh24); + str += " wh25=" + TestBattery1(status.single, (byte)_sig_sen.wh25); + str += " wh26=" + TestBattery1(status.single, (byte)_sig_sen.wh26); + str += " wh40=" + TestBattery1(status.single, (byte)_sig_sen.wh40); cumulus.LogDebugMessage(str); - str = "wh31> ch1=" + testBattery1(status.wh31, (byte)_wh31_ch.ch1); - str += " ch2=" + testBattery1(status.wh31, (byte)_wh31_ch.ch2); - str += " ch3=" + testBattery1(status.wh31, (byte)_wh31_ch.ch3); - str += " ch4=" + testBattery1(status.wh31, (byte)_wh31_ch.ch4); - str += " ch5=" + testBattery1(status.wh31, (byte)_wh31_ch.ch5); - str += " ch6=" + testBattery1(status.wh31, (byte)_wh31_ch.ch6); - str += " ch7=" + testBattery1(status.wh31, (byte)_wh31_ch.ch7); - str += " ch8=" + testBattery1(status.wh31, (byte)_wh31_ch.ch8); + str = "wh31> ch1=" + TestBattery1(status.wh31, (byte)_wh31_ch.ch1); + str += " ch2=" + TestBattery1(status.wh31, (byte)_wh31_ch.ch2); + str += " ch3=" + TestBattery1(status.wh31, (byte)_wh31_ch.ch3); + str += " ch4=" + TestBattery1(status.wh31, (byte)_wh31_ch.ch4); + str += " ch5=" + TestBattery1(status.wh31, (byte)_wh31_ch.ch5); + str += " ch6=" + TestBattery1(status.wh31, (byte)_wh31_ch.ch6); + str += " ch7=" + TestBattery1(status.wh31, (byte)_wh31_ch.ch7); + str += " ch8=" + TestBattery1(status.wh31, (byte)_wh31_ch.ch8); cumulus.LogDebugMessage(str); - str = "wh41> ch1=" + testBattery2(status.wh41, 0x0F); - str += " ch2=" + testBattery2((UInt16)(status.wh41 >> 4), 0x0F); - str += " ch3=" + testBattery2((UInt16)(status.wh41 >> 8), 0x0F); - str += " ch4=" + testBattery2((UInt16)(status.wh41 >> 12), 0x0F); + str = "wh41> ch1=" + TestBattery2(status.wh41, 0x0F); + str += " ch2=" + TestBattery2((UInt16)(status.wh41 >> 4), 0x0F); + str += " ch3=" + TestBattery2((UInt16)(status.wh41 >> 8), 0x0F); + str += " ch4=" + TestBattery2((UInt16)(status.wh41 >> 12), 0x0F); cumulus.LogDebugMessage(str); - str = "wh51> ch1=" + testBattery1(status.wh51, (byte)_wh51_ch.ch1); - str += " ch2=" + testBattery1(status.wh31, (byte)_wh51_ch.ch2); - str += " ch3=" + testBattery1(status.wh31, (byte)_wh51_ch.ch3); - str += " ch4=" + testBattery1(status.wh31, (byte)_wh51_ch.ch4); - str += " ch5=" + testBattery1(status.wh31, (byte)_wh51_ch.ch5); - str += " ch6=" + testBattery1(status.wh31, (byte)_wh51_ch.ch6); - str += " ch7=" + testBattery1(status.wh31, (byte)_wh51_ch.ch7); - str += " ch8=" + testBattery1(status.wh31, (byte)_wh51_ch.ch8); + str = "wh51> ch1=" + TestBattery1(status.wh51, (byte)_wh51_ch.ch1); + str += " ch2=" + TestBattery1(status.wh31, (byte)_wh51_ch.ch2); + str += " ch3=" + TestBattery1(status.wh31, (byte)_wh51_ch.ch3); + str += " ch4=" + TestBattery1(status.wh31, (byte)_wh51_ch.ch4); + str += " ch5=" + TestBattery1(status.wh31, (byte)_wh51_ch.ch5); + str += " ch6=" + TestBattery1(status.wh31, (byte)_wh51_ch.ch6); + str += " ch7=" + TestBattery1(status.wh31, (byte)_wh51_ch.ch7); + str += " ch8=" + TestBattery1(status.wh31, (byte)_wh51_ch.ch8); cumulus.LogDebugMessage(str); - cumulus.LogDebugMessage("wh57> " + testBattery3(status.wh57)); + cumulus.LogDebugMessage("wh57> " + TestBattery3(status.wh57)); cumulus.LogDebugMessage("wh68> " + (0.02 * status.wh68) + "V"); cumulus.LogDebugMessage("wh80> " + (0.02 * status.wh80) + "V"); - str = "wh55> ch1=" + testBattery3(status.wh55_ch1); - str += " ch2=" + testBattery3(status.wh55_ch2); - str += " ch3=" + testBattery3(status.wh55_ch2); - str += " ch4=" + testBattery3(status.wh55_ch2); + str = "wh55> ch1=" + TestBattery3(status.wh55_ch1); + str += " ch2=" + TestBattery3(status.wh55_ch2); + str += " ch3=" + TestBattery3(status.wh55_ch2); + str += " ch4=" + TestBattery3(status.wh55_ch2); cumulus.LogDebugMessage(str); } - private string testBattery1(byte value, byte mask) + private string TestBattery1(byte value, byte mask) { if ((value & mask) == 0) return "OK"; else return "Low"; } - private string testBattery1(UInt16 value, UInt16 mask) + private string TestBattery1(UInt16 value, UInt16 mask) { if ((value & mask) == 0) return "OK"; @@ -903,7 +906,7 @@ private string testBattery1(UInt16 value, UInt16 mask) return "Low"; } - private string testBattery2(UInt16 value, UInt16 mask) + private string TestBattery2(UInt16 value, UInt16 mask) { if ((value & mask) > 1) return "OK"; @@ -911,7 +914,7 @@ private string testBattery2(UInt16 value, UInt16 mask) return "Low"; } - private string testBattery3(byte value) + private string TestBattery3(byte value) { if (value > 1) return "OK"; @@ -935,7 +938,7 @@ public static object RawDeserialize(byte[] rawData, int position, Type anyType) private struct CommandPayload { private readonly ushort Header; - public byte Command; + private readonly byte Command; private readonly byte Size; //public byte[] Data; private readonly byte Checksum; @@ -943,6 +946,7 @@ private struct CommandPayload //public CommandPayload(byte command, byte[] data) : this() public CommandPayload(byte command) : this() { + //ushort header; this.Header = 0xffff; this.Command = command; this.Size = (byte) (Marshal.SizeOf(typeof(CommandPayload)) - 3); @@ -1033,7 +1037,7 @@ private bool ChecksumOK(byte[] data, int lengthBytes) } else { - size = convertBigEndianUInt16(data, 3); + size = ConvertBigEndianUInt16(data, 3); } byte checksum = (byte)(data[2] + data[3]); @@ -1053,53 +1057,52 @@ private bool ChecksumOK(byte[] data, int lengthBytes) } } - private UInt16 convertBigEndianUInt16(byte[] array, int start) + private static UInt16 ConvertBigEndianUInt16(byte[] array, int start) { return (UInt16)(array[start] << 8 | array[start+1]); } - private Int16 convertBigEndianInt16(byte[] array, int start) + private static Int16 ConvertBigEndianInt16(byte[] array, int start) { return (Int16)((array[start] << 8) + array[start + 1]); } - private UInt32 convertBigEndianUInt32(byte[] array, int start) + private static UInt32 ConvertBigEndianUInt32(byte[] array, int start) { return (UInt32)(array[start++] << 24 | array[start++] << 16 | array[start++] << 8 | array[start]); } private void CheckHighGust(double gust, int gustdir, DateTime timestamp) { - if (gust > RecentMaxGust) - { - if (gust > highgusttoday) - { - highgusttoday = gust; - highgusttodaytime = timestamp; - highgustbearing = gustdir; - WriteTodayFile(timestamp, false); - } - if (gust > HighGustThisMonth) - { - HighGustThisMonth = gust; - HighGustThisMonthTS = timestamp; - WriteMonthIniFile(); - } - if (gust > HighGustThisYear) - { - HighGustThisYear = gust; - HighGustThisYearTS = timestamp; - WriteYearIniFile(); - } - // All time high gust? - if (gust > alltimerecarray[AT_highgust].value) - { - SetAlltime(AT_highgust, gust, timestamp); - } + if (!(gust > RecentMaxGust)) return; - // check for monthly all time records (and set) - CheckMonthlyAlltime(AT_highgust, gust, true, timestamp); + if (gust > highgusttoday) + { + highgusttoday = gust; + highgusttodaytime = timestamp; + highgustbearing = gustdir; + WriteTodayFile(timestamp, false); } + if (gust > HighGustThisMonth) + { + HighGustThisMonth = gust; + HighGustThisMonthTS = timestamp; + WriteMonthIniFile(); + } + if (gust > HighGustThisYear) + { + HighGustThisYear = gust; + HighGustThisYearTS = timestamp; + WriteYearIniFile(); + } + // All time high gust? + if (gust > alltimerecarray[AT_highgust].value) + { + SetAlltime(AT_highgust, gust, timestamp); + } + + // check for monthly all time records (and set) + CheckMonthlyAlltime(AT_highgust, gust, true, timestamp); } diff --git a/CumulusMX/Properties/AssemblyInfo.cs b/CumulusMX/Properties/AssemblyInfo.cs index 9f80d7c8..62593a1e 100644 --- a/CumulusMX/Properties/AssemblyInfo.cs +++ b/CumulusMX/Properties/AssemblyInfo.cs @@ -6,7 +6,7 @@ // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("CumulusMX")] -[assembly: AssemblyDescription("Build 3057")] +[assembly: AssemblyDescription("Build 3058")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CumulusMX")] @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.2.1.3057")] -[assembly: AssemblyFileVersion("3.2.1.3057")] +[assembly: AssemblyVersion("3.2.2.3058")] +[assembly: AssemblyFileVersion("3.2.2.3058")] diff --git a/CumulusMX/WeatherStation.cs b/CumulusMX/WeatherStation.cs index 31ef7d6e..30d19cef 100644 --- a/CumulusMX/WeatherStation.cs +++ b/CumulusMX/WeatherStation.cs @@ -3816,6 +3816,31 @@ public void SetAlltime(int index, double value, DateTime timestamp) } } + public void SetMonthlyAlltime(int index, double value, DateTime timestamp) + { + lock (monthlyalltimeIniThreadLock) + { + var month = timestamp.Month; + + double oldvalue = monthlyrecarray[index, month].value; + DateTime oldts = monthlyrecarray[index, month].timestamp; + + string s = "Changed monthly record, month = " + month + ": "; + s = s + timestamp.ToString("yyyy-MM-dd") + FormatDateTime(" HH", timestamp) + ":" + FormatDateTime("mm ", timestamp); + s = s + value.ToString("F3") + " \"" + alltimedescs[index] + "\" "; + s = s + FormatDateTime("yyyy-MM-dd", oldts) + FormatDateTime(" HH", oldts) + ":" + FormatDateTime("mm ", oldts); + s = s + oldvalue.ToString("F3"); + + cumulus.LogMessage(s); + + monthlyrecarray[index, month].data_type = index; + monthlyrecarray[index, month].value = value; + + WriteMonthlyAlltimeIniFile(); + } + } + + /// /// Returns the angle from bearing2 to bearing1, in the range -180 to +180 degrees diff --git a/Updates.txt b/Updates.txt index c5117098..f444231b 100644 --- a/Updates.txt +++ b/Updates.txt @@ -1,3 +1,20 @@ +3.2.2 - b3058 +============= +- Implements the missing <#txbattery> web tag for WLL devices +- Fix default website pages header not wrapping on small screens +- Adds Monthly Records editor +- Fixes and improvements to the All Time Records editor + +- Updated files + \CumulusMX.exe + \interface\.html + \web\T.htm + +- New files + \interface\monthlyrecseditor.html + \interface\js\monthlyrecseditor.js + + 3.2.1 - b3057 ============= - Fix for WMR200 stations writing a zero value Apparent Temperature to the log files when retrieving logger data