From 9c28c3010034f9f80def8332fef0ee7a1ab3f93d Mon Sep 17 00:00:00 2001 From: Mark Crossley <1196094+mcrossley@users.noreply.github.com> Date: Thu, 5 Mar 2020 18:06:58 +0000 Subject: [PATCH] b3066 --- CumulusMX/AlarmSettings.cs | 15 +- CumulusMX/Cumulus.cs | 23 ++- CumulusMX/DavisWllStation.cs | 241 +++++++++++++++------------ CumulusMX/GW1000Station.cs | 96 ++++++++++- CumulusMX/Properties/AssemblyInfo.cs | 6 +- Updates.txt | 17 ++ 6 files changed, 287 insertions(+), 111 deletions(-) diff --git a/CumulusMX/AlarmSettings.cs b/CumulusMX/AlarmSettings.cs index 937d30e2..5caa929e 100644 --- a/CumulusMX/AlarmSettings.cs +++ b/CumulusMX/AlarmSettings.cs @@ -82,7 +82,11 @@ public string GetAlarmSettings() contactLostEnabled = cumulus.SensorAlarmEnabled, contactLostSoundEnabled = cumulus.SensorAlarmSound, - contactLostSound = cumulus.SensorAlarmSoundFile + contactLostSound = cumulus.SensorAlarmSoundFile, + + dataStoppedEnabled = cumulus.DataStoppedAlarmEnabled, + dataStoppedSoundEnabled = cumulus.DataStoppedAlarmSound, + dataStoppedSound = cumulus.DataStoppedAlarmSoundFile }; var retObject = new JsonAlarmSettings() @@ -164,6 +168,10 @@ public string UpdateAlarmSettings(IHttpContext context) cumulus.SensorAlarmSound = settings.contactLostSoundEnabled; cumulus.SensorAlarmSoundFile = settings.contactLostSound; + cumulus.DataStoppedAlarmEnabled = settings.dataStoppedEnabled; + cumulus.DataStoppedAlarmSound = settings.dataStoppedSoundEnabled; + cumulus.DataStoppedAlarmSoundFile = settings.dataStoppedSound; + // Save the settings cumulus.WriteIniFile(); @@ -234,6 +242,11 @@ public class JsonAlarmSettingsData public bool contactLostEnabled; public bool contactLostSoundEnabled; public string contactLostSound; + + public bool dataStoppedEnabled; + public bool dataStoppedSoundEnabled; + public string dataStoppedSound; + } public class JsonAlarmUnits diff --git a/CumulusMX/Cumulus.cs b/CumulusMX/Cumulus.cs index 7e4b3fd5..c4687b12 100644 --- a/CumulusMX/Cumulus.cs +++ b/CumulusMX/Cumulus.cs @@ -30,8 +30,8 @@ namespace CumulusMX public class Cumulus { ///////////////////////////////// - public string Version = "3.4.1"; - public string Build = "3065"; + public string Version = "3.4.2"; + public string Build = "3066"; ///////////////////////////////// private const string appGuid = "57190d2e-7e45-4efb-8c09-06a176cef3f3"; @@ -3437,6 +3437,11 @@ private void ReadIniFile() SensorAlarmSoundFile = ini.GetValue("Alarms", "SensorAlarmSoundFile", DefaultSoundFile); if (SensorAlarmSoundFile.Contains(DefaultSoundFileOld)) SensorAlarmSoundFile = DefaultSoundFile; + DataStoppedAlarmEnabled = ini.GetValue("Alarms", "DataStoppedAlarmSet", false); + DataStoppedAlarmSound = ini.GetValue("Alarms", "DataStoppedAlarmSound", false); + DataStoppedAlarmSoundFile = ini.GetValue("Alarms", "DataStoppedlarmSoundFile", DefaultSoundFile); + if (DataStoppedAlarmSoundFile.Contains(DefaultSoundFileOld)) SensorAlarmSoundFile = DefaultSoundFile; + PressOffset = ini.GetValue("Offsets", "PressOffset", 0.0); TempOffset = ini.GetValue("Offsets", "TempOffset", 0.0); HumOffset = ini.GetValue("Offsets", "HumOffset", 0); @@ -3938,6 +3943,10 @@ internal void WriteIniFile() ini.SetValue("Alarms", "SensorAlarmSound", SensorAlarmSound); ini.SetValue("Alarms", "SensorAlarmSoundFile", SensorAlarmSoundFile); + ini.SetValue("Alarms", "DataStoppedAlarmSet", DataStoppedAlarmEnabled); + ini.SetValue("Alarms", "DataStoppedAlarmSound", DataStoppedAlarmSound); + ini.SetValue("Alarms", "DataStoppedAlarmSoundFile", DataStoppedAlarmSoundFile); + ini.SetValue("Offsets", "PressOffset", PressOffset); ini.SetValue("Offsets", "TempOffset", TempOffset); ini.SetValue("Offsets", "HumOffset", HumOffset); @@ -4350,6 +4359,14 @@ private void ReadStringsFile() } } + public string DataStoppedAlarmSoundFile { get; set; } + + public bool DataStoppedAlarmSound { get; set; } + + public bool DataStoppedAlarmEnabled { get; set; } + + //public bool DataStoppedAlarmState { get; set; } + public string SensorAlarmSoundFile { get; set; } public bool SensorAlarmSound { get; set; } @@ -6582,7 +6599,7 @@ public void StartTimers() // start the general one-minute timer LogMessage("Starting 1-minute timer"); station.StartMinuteTimer(); - LogMessage("Data logging intverval = " + DataLogInterval); + LogMessage("Data logging interval = " + DataLogInterval); if (RealtimeFTPEnabled) { diff --git a/CumulusMX/DavisWllStation.cs b/CumulusMX/DavisWllStation.cs index 5b028d41..fbc74208 100644 --- a/CumulusMX/DavisWllStation.cs +++ b/CumulusMX/DavisWllStation.cs @@ -33,7 +33,7 @@ internal class DavisWllStation : WeatherStation private int MaxArchiveRuns = 1; private static readonly HttpClientHandler HistoricHttpHandler = new HttpClientHandler(); private readonly HttpClient WlHttpClient = new HttpClient(HistoricHttpHandler); - private bool checkWllGustValues; + private readonly bool checkWllGustValues; private bool broadcastReceived = false; public DavisWllStation(Cumulus cumulus) : base(cumulus) @@ -358,100 +358,108 @@ private void DecodeBroadcast(string broadcastJson) { cumulus.LogDataMessage("WLL Broadcast: " + broadcastJson); - var data = Newtonsoft.Json.Linq.JObject.Parse(broadcastJson); - - // The WLL sends the timestamp in Unix ticks, and in UTC - // rather than rely on the WLL clock being correct, we will use our local time - //var dateTime = FromUnixTime((int)data["ts"]); - var dateTime = DateTime.Now; - foreach (var rec in data["conditions"]) + // sanity check + if (broadcastJson.StartsWith("{\"did\":")) { - var txid = (int)rec["txid"]; - - // Wind - /* Available fields: - * rec["wind_speed_last"] - * rec["wind_dir_last"] - * rec["wind_speed_hi_last_10_min"] - * rec["wind_dir_at_hi_speed_last_10_min"] - */ - if (cumulus.WllPrimaryWind == txid) + var data = Newtonsoft.Json.Linq.JObject.Parse(broadcastJson); + + // The WLL sends the timestamp in Unix ticks, and in UTC + // rather than rely on the WLL clock being correct, we will use our local time + //var dateTime = FromUnixTime((int)data["ts"]); + var dateTime = DateTime.Now; + foreach (var rec in data["conditions"]) { - 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}"); - } - else - { - // No average in the broadcast data, so use last value from current - allow for calibration - DoWind((double)rec["wind_speed_last"], (int)rec["wind_dir_last"], WindAverage / cumulus.WindSpeedMult, dateTime); + var txid = (int)rec["txid"]; - if (checkWllGustValues) + // Wind + /* Available fields: + * rec["wind_speed_last"] + * rec["wind_dir_last"] + * rec["wind_speed_hi_last_10_min"] + * rec["wind_dir_at_hi_speed_last_10_min"] + */ + if (cumulus.WllPrimaryWind == txid) + { + if (string.IsNullOrEmpty((string)rec["wind_speed_last"]) || string.IsNullOrEmpty((string)rec["wind_dir_last"])) { - var gust = ConvertWindMPHToUser((double)rec["wind_speed_hi_last_10_min"]) * cumulus.WindGustMult; + cumulus.LogDebugMessage($"WLL broadcast: no valid wind speed found [speed={(string)rec["wind_speed_last"]}, dir= {(string)rec["wind_dir_last"]}] on TxId {txid}"); + } + else + { + // No average in the broadcast data, so use last value from current - allow for calibration + DoWind((double)rec["wind_speed_last"], (int)rec["wind_dir_last"], WindAverage / cumulus.WindSpeedMult, dateTime); - if (gust > RecentMaxGust) + if (checkWllGustValues) { - // See if the station 10 min high speed is higher than our current 10-min max - // ie we missed the high gust - cumulus.LogDebugMessage("Setting max gust from broadcast 10 min high value: " + gust.ToString(cumulus.WindFormat) + " was: " + RecentMaxGust.ToString(cumulus.WindFormat)); - - CheckHighGust(gust, (int)rec["wind_dir_at_hi_speed_last_10_min"], dateTime); - // add to recent values so normal calculation includes this value - WindRecent[nextwind].Gust = gust / cumulus.WindGustMult; - WindRecent[nextwind].Speed = WindAverage / cumulus.WindSpeedMult; - WindRecent[nextwind].Timestamp = dateTime; - nextwind = (nextwind + 1) % cumulus.MaxWindRecent; - - RecentMaxGust = gust; + var gust = ConvertWindMPHToUser((double)rec["wind_speed_hi_last_10_min"]) * cumulus.WindGustMult; + + if (gust > RecentMaxGust) + { + // See if the station 10 min high speed is higher than our current 10-min max + // ie we missed the high gust + cumulus.LogDebugMessage("Setting max gust from broadcast 10 min high value: " + gust.ToString(cumulus.WindFormat) + " was: " + RecentMaxGust.ToString(cumulus.WindFormat)); + + CheckHighGust(gust, (int)rec["wind_dir_at_hi_speed_last_10_min"], dateTime); + // add to recent values so normal calculation includes this value + WindRecent[nextwind].Gust = gust / cumulus.WindGustMult; + WindRecent[nextwind].Speed = WindAverage / cumulus.WindSpeedMult; + WindRecent[nextwind].Timestamp = dateTime; + nextwind = (nextwind + 1) % cumulus.MaxWindRecent; + + RecentMaxGust = gust; + } + } + else if (!CalcRecentMaxGust) + { + RecentMaxGust = ConvertWindMPHToUser((double)rec["wind_speed_hi_last_10_min"]) * cumulus.WindGustMult; + CheckHighGust(RecentMaxGust, (int)rec["wind_dir_at_hi_speed_last_10_min"], dateTime); } - } - else if (!CalcRecentMaxGust) - { - RecentMaxGust = ConvertWindMPHToUser((double) rec["wind_speed_hi_last_10_min"]) *cumulus.WindGustMult; - CheckHighGust(RecentMaxGust, (int)rec["wind_dir_at_hi_speed_last_10_min"], dateTime); } } - } - - // Rain - /* - * All fields are *tip counts* - * Available fields: - * rec["rain_size"] - 0: Reseverved, 1: 0.01", 2: 0.2mm, 3: 0.1mm, 4: 0.001" - * rec["rain_rate_last"] - * rec["rain_15_min"] - * rec["rain_60_min"] - * rec["rain_24_hr"] - * rec["rain_storm"] - * rec["rain_storm_start_at"] - * rec["rainfall_daily"] - * rec["rainfall_monthly"] - * rec["rainfall_year"]) - */ - 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 - { - 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) + // Rain + /* + * All fields are *tip counts* + * Available fields: + * rec["rain_size"] - 0: Reseverved, 1: 0.01", 2: 0.2mm, 3: 0.1mm, 4: 0.001" + * rec["rain_rate_last"] + * rec["rain_15_min"] + * rec["rain_60_min"] + * rec["rain_24_hr"] + * rec["rain_storm"] + * rec["rain_storm_start_at"] + * rec["rainfall_daily"] + * rec["rainfall_monthly"] + * rec["rainfall_year"]) + */ + 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"])) { - rainrate = 0; + cumulus.LogDebugMessage($"WLL broadcast: no valid rainfall found [total={(string)rec["rainfall_year"]}, rate= {(string)rec["rain_rate_last"]}] on TxId {txid}"); } + else + { + var rain = ConvertRainClicksToUser((double)rec["rainfall_year"], (int)rec["rain_size"]); + var rainrate = ConvertRainClicksToUser((double)rec["rain_rate_last"], (int)rec["rain_size"]); - DoRain(rain, rainrate, dateTime); + if (rainrate < 0) + { + rainrate = 0; + } + + DoRain(rain, rainrate, dateTime); + } } - } - UpdateStatusPanel(DateTime.Now); + UpdateStatusPanel(DateTime.Now); - broadcastReceived = true; - DataStopped = false; + broadcastReceived = true; + DataStopped = false; + } + else + { + cumulus.LogMessage("WLL broadcast: Invalid payload in message"); + } } catch (Exception exp) { @@ -1056,7 +1064,7 @@ private void OnServiceChanged(object sender, ServiceAnnouncementEventArgs e) private void OnServiceRemoved(object sender, ServiceAnnouncementEventArgs e) { - PrintService('-', e.Announcement); + cumulus.LogMessage("ZeroConfig Service: WLL service has been removed!"); } private void OnServiceAdded(object sender, ServiceAnnouncementEventArgs e) @@ -1296,7 +1304,7 @@ private void GetWlHistoricData() return; } - if (cumulus.WllStationId == String.Empty) + if (cumulus.WllStationId == String.Empty || int.Parse(cumulus.WllStationId) < 10) { var msg = "No WeatherLink API station ID in the cumulus.ini file"; cumulus.LogMessage(msg); @@ -1307,8 +1315,6 @@ private void GetWlHistoricData() } } - Console.WriteLine("Downloading Historic Data from WL.com"); - //int passCount; //const int maxPasses = 4; @@ -1325,6 +1331,9 @@ private void GetWlHistoricData() MaxArchiveRuns++; } + Console.WriteLine($"Downloading Historic Data from WL.com from: {cumulus.LastUpdateTime.ToString("s")} to: {FromUnixTime(endTime).ToString("s")}"); + cumulus.LogMessage($"Downloading Historic Data from WL.com from: {cumulus.LastUpdateTime.ToString("s")} to: {FromUnixTime(endTime).ToString("s")}"); + SortedDictionary parameters = new SortedDictionary(); parameters.Add("api-key", cumulus.WllApiKey); parameters.Add("station-id", cumulus.WllStationId.ToString()); @@ -1388,33 +1397,49 @@ private void GetWlHistoricData() cumulus.LogMessage("WeatherLink API Historic Error: " + (string)jObject["code"] + ", " + (string)jObject["message"]); return; } - // get the sensor data - sensorData = jObject["sensors"]; - foreach (Newtonsoft.Json.Linq.JToken sensor in sensorData) + if (responseBody == "{}") + { + cumulus.LogMessage("WeatherLink API Historic: No data was returned. Check your Device Id."); + Console.WriteLine(" - No historic data available"); + cumulus.LastUpdateTime = FromUnixTime(endTime); + return; + } + else if (responseBody.StartsWith("{\"sensors\":[{\"lsid\"")) // sanity check { - if ((int)sensor["sensor_type"] != 504) + // get the sensor data + sensorData = jObject["sensors"]; + + foreach (Newtonsoft.Json.Linq.JToken sensor in sensorData) { - var recs = sensor["data"].Count(); - if (recs > noOfRecs) - noOfRecs = recs; + if ((int)sensor["sensor_type"] != 504) + { + var recs = sensor["data"].Count(); + if (recs > noOfRecs) + noOfRecs = recs; + } } - } - if (noOfRecs == 0) - { - cumulus.LogMessage("No historic data available"); - Console.WriteLine(" - No historic data available"); - return; + if (noOfRecs == 0) + { + cumulus.LogMessage("No historic data available"); + Console.WriteLine(" - No historic data available"); + return; + } + else + { + cumulus.LogMessage($"Found {noOfRecs} historic records to process"); + } } - else + else // No idea what we got, dump it to the log { - cumulus.LogMessage($"Found {noOfRecs} historic records to process"); + cumulus.LogMessage("Invalid historic message received"); + cumulus.LogDataMessage("Received: " + responseBody); } } catch (Exception ex) { - cumulus.LogDebugMessage("GetWlHistoricData exception: " + ex.Message); + cumulus.LogMessage("GetWlHistoricData exception: " + ex.Message); } for (int dataIndex = 0; dataIndex < noOfRecs; dataIndex++) @@ -1499,7 +1524,7 @@ private void GetWlHistoricData() } catch (Exception ex) { - cumulus.LogDebugMessage("GetWlHistoricData exception: " + ex.Message); + cumulus.LogMessage("GetWlHistoricData exception: " + ex.Message); } } @@ -2136,7 +2161,7 @@ private async void GetWlCurrentData() return; } - if (cumulus.WllStationId == String.Empty) + if (cumulus.WllStationId == String.Empty || int.Parse(cumulus.WllStationId) < 10) { cumulus.LogMessage("No WeatherLink API station ID in the cumulus.ini file"); if (!GetAvailableStationIds()) @@ -2194,6 +2219,12 @@ private async void GetWlCurrentData() return; } + if (responseBody == "{}") + { + cumulus.LogMessage("WeatherLink API Current: No data was returned. Check your Device Id."); + return; + } + // get the sensor data JToken sensorData = jObject["sensors"]; @@ -2302,11 +2333,15 @@ private void BroadcastTimeout(object source, ElapsedEventArgs e) if (broadcastReceived) { broadcastReceived = false; + DataStopped = false; } else { - cumulus.LogMessage("ERROR: No broadcast data received from the WLL for 30 seconds"); + cumulus.LogMessage($"ERROR: No broadcast data received from the WLL for {tmrBroadcastWatchdog.Interval / 1000} seconds"); DataStopped = true; + UpdateStatusPanel(DateTime.Now); + // Try and give the broadcasts a kick in case the last command did not get through + GetWllRealtime(null, null); } } } diff --git a/CumulusMX/GW1000Station.cs b/CumulusMX/GW1000Station.cs index 70ff3a8e..39ecf1ef 100644 --- a/CumulusMX/GW1000Station.cs +++ b/CumulusMX/GW1000Station.cs @@ -5,6 +5,8 @@ using System.Text; using System.Threading; using System.Runtime.InteropServices; +using System.Net; +using System.Timers; namespace CumulusMX { @@ -17,6 +19,10 @@ internal class GW1000Station : WeatherStation private TcpClient socket; private bool connectedOK = false; + private bool dataReceived = false; + + private readonly System.Timers.Timer tmrDataWatchdog; + private enum Commands : byte { // General order @@ -199,9 +205,24 @@ public GW1000Station(Cumulus cumulus) : base(cumulus) cumulus.UseWind10MinAve = true; cumulus.UseSpeedForAvgCalc = false; + tmrDataWatchdog = new System.Timers.Timer(); + + ipaddr = cumulus.Gw1000IpAddress; - cumulus.LogMessage("IP address = " + ipaddr + " Port = " + AT_port); + var discoveredIP = DiscoverGW1000(); + + if (discoveredIP != "0" && discoveredIP != ipaddr) + { + cumulus.LogMessage($"Discovered a new IP address for the GW1000: {discoveredIP}"); + cumulus.LogMessage($"Changing previous IP address: {ipaddr} to {discoveredIP}"); + ipaddr = discoveredIP; + cumulus.Gw1000IpAddress = ipaddr; + cumulus.WriteIniFile(); + } + + + cumulus.LogMessage("Using IP address = " + ipaddr + " Port = " + AT_port); socket = OpenTcpPort(); connectedOK = socket != null; @@ -295,6 +316,12 @@ public override void Start() tenMinuteChanged = true; lastMinute = DateTime.Now.Minute; + // Start a broadcast watchdog to warn if WLL broadcast messages are not being received + tmrDataWatchdog.Elapsed += DataTimeout; + tmrDataWatchdog.Interval = 1000 * 30; // timeout after 30 seconds + tmrDataWatchdog.AutoReset = true; + tmrDataWatchdog.Start(); + try { while (!Program.exitSystem) @@ -357,6 +384,53 @@ private void bw_DoStart(object sender, DoWorkEventArgs e) Cumulus.syncInit.Release(); } + private string DiscoverGW1000() + { + var udp = new UdpClient(); + var BroadcastPort = 46000; + var ClientPort = 59387; + + var receiveEp = new IPEndPoint(IPAddress.Any, ClientPort); + //var client = new UdpClient(ClientPort); + + var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + socket.ReceiveTimeout = 2000; + socket.Bind(receiveEp); + //socket.Listen(1); + + var groupEp = new IPEndPoint(IPAddress.Broadcast, BroadcastPort); + var sendBytes = new byte[] { 0xff, 0xff, 0x12, 0x03, 0x15 }; + + udp.EnableBroadcast = true; + udp.Send(sendBytes, sendBytes.Length, groupEp); + + var receivedBytes = new byte[35]; + socket.Receive(receivedBytes, 0, receivedBytes.Length, SocketFlags.None); + + string ipAddr = $"{receivedBytes[11]}.{receivedBytes[12]}.{receivedBytes[13]}.{receivedBytes[14]}"; + + udp.Close(); + socket.Close(); + + if (ipAddr.Split(new char[] {'.'}, StringSplitOptions.RemoveEmptyEntries).Length == 4) + { + IPAddress ipAddr2; + if (IPAddress.TryParse(ipAddr, out ipAddr2)) + { + cumulus.LogDebugMessage($"debug: Discovered GW1000 at address {ipaddr}"); + return ipAddr; + } + else + { + return "0"; + } + } + else + { + return "0"; + } + } + private string GetFirmwareVersion() { var response = "???"; @@ -749,6 +823,9 @@ public void GetLiveData() DoForecast("", false); UpdateStatusPanel(dateTime); + + dataReceived = true; + DataStopped = false; } else { @@ -891,6 +968,7 @@ private string TestBattery1(byte value, byte mask) else return "Low"; } + private string TestBattery1(UInt16 value, UInt16 mask) { if ((value & mask) == 0) @@ -1115,5 +1193,21 @@ private double ConvertKmtoUserUnits(double val) } return val; } + + private void DataTimeout(object source, ElapsedEventArgs e) + { + if (dataReceived) + { + dataReceived = false; + DataStopped = false; + } + else + { + cumulus.LogMessage($"ERROR: No data received from the GW1000 for {tmrDataWatchdog.Interval / 1000} seconds"); + DataStopped = true; + UpdateStatusPanel(DateTime.Now); + } + } + } } diff --git a/CumulusMX/Properties/AssemblyInfo.cs b/CumulusMX/Properties/AssemblyInfo.cs index f6efcc2f..72c6d963 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 3065")] +[assembly: AssemblyDescription("Build 3066")] [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.4.1.3065")] -[assembly: AssemblyFileVersion("3.4.1.3065")] +[assembly: AssemblyVersion("3.4.2.3066")] +[assembly: AssemblyFileVersion("3.4.2.3066")] diff --git a/Updates.txt b/Updates.txt index 91fcfcfc..65293021 100644 --- a/Updates.txt +++ b/Updates.txt @@ -1,3 +1,20 @@ +3.4.2 - b3066 +============= +- Improved error handing for invalid Davis WLL Station Ids +- Improved error handling when the network connection to a Davis WLL is lost (and restored) +- Adds missing Data Stopped alarm to the Dashboard and Alarm Settings screens +- Adds auto-discovery for Ecowitt GW1000 devices IP addresses +- Adds DataStopped handling to Ecowitt GW1000 devices + +- Updated files + \CumulusMX.exe + \interface\alarmsettings.html + \interface\index.html + \interface\js\alarmsettings.js + \interface\js\dashboard.js + + + 3.4.1 - b3065 ============= - Fix for WLL if you change the WL.com logging interval around a catch-up period