private async static Task <int> Weather(Predictions predictions) { var querycount = 0; predictions.OnQuery += () => { querycount++; }; // this should cause a query var weather = await predictions.CurrentWeather(); foreach (var w in weather) { Console.WriteLine($"{w.Date} {w.Type} {w.StrValue} {w.Value}"); } if (weather.Count == 0 || querycount != 2) { throw new Exception($"Invalid query : {weather.Count} {querycount}"); } var previousquerycount = querycount; // this round should not cause a query weather = await predictions.CurrentWeather(); if (weather.Count == 0 || querycount != previousquerycount) { throw new Exception($"Invalid query : {weather.Count} {querycount}"); } return(0); }
private async void FrameUpdate(object state) { if (Canvas == null) { throw new Exception("must have a valid canvas to draw too"); } // the timer is reentrant, so only allow one instance to run if (System.Threading.Interlocked.CompareExchange(ref FrameLock, 1, 0) != 0) { return; } // grab predictions var weather = await Prediction.CurrentWeather(); var weatherStation = await Prediction.CurrentWeatherStation(); var rowheight = 26f * Ratio; var fontsize = 18f * Ratio; var fontname = "Courier New"; var point = new Point() { X = 0f, Y = 0f }; var avoiddups = new HashSet <string>(); try { await Canvas.SuspendLayout(); // clear Canvas.Clear(RGBA.Black); // current weather point.Y = (rowheight * 0); Canvas.Text(RGBA.White, point, "Local weather", fontsize, fontname); foreach (var w in weather.OrderByDescending(wr => wr.Date)) { if (avoiddups.Contains(w.Type)) { continue; } switch (w.Type) { case "temperature": point.X = 0f; point.Y = (rowheight * 1); Canvas.Text(RGBA.White, point, $"current: {w.Value}°", fontsize, fontname); break; case "temperaturetrend": point.X = (rowheight * 6); point.Y = (rowheight * 1); Canvas.Text(RGBA.White, point, $"[{w.StrValue.ToLower()}]", fontsize, fontname); break; case "temperaturelow": point.X = 0f; point.Y = (rowheight * 2); Canvas.Text(RGBA.White, point, $"low: {w.Value}°", fontsize, fontname); break; case "temperaturehigh": point.X = 0f; point.Y = (rowheight * 3); Canvas.Text(RGBA.White, point, $"high: {w.Value}°", fontsize, fontname); break; case "winddirection": point.X = 0f; point.Y = (rowheight * 4); Canvas.Text(RGBA.White, point, $"wind: {w.StrValue}", fontsize, fontname); break; case "windspeed": point.X = (rowheight * 6); point.Y = (rowheight * 4); Canvas.Text(RGBA.White, point, $"{w.StrValue.ToLower()}", fontsize, fontname); break; case "shortforecast": point.X = 0f; point.Y = (rowheight * 5); var description = SplitString(w.StrValue, maxlength: 23); Canvas.Text(RGBA.White, point, $"{description.Item1}", fontsize, fontname); point.Y = (rowheight * 6); Canvas.Text(RGBA.White, point, $"{description.Item2}", fontsize, fontname); // debug if (true) { point.X = 0f; point.Y = (rowheight * 7); Canvas.Text(RGBA.White, point, $"{w.Date.ToLocalTime():yyyy/MM/dd hh:mm}", fontsize * 0.5f, fontname); } break; } avoiddups.Add(w.Type); } // weather station if (weatherStation.Count > 0) { var padding = (rowheight * 10); point.Y = (rowheight * 0); point.X = padding; Canvas.Text(RGBA.White, point, $"Weather Station", fontsize, fontname); // capture all the values var data = new AcuriteData(); foreach (var w in weatherStation.OrderByDescending(s => s.Date)) { if (data.utcDate == default(DateTime)) { data.utcDate = w.Date; } switch (w.Type) { case "outtemperature": if (!data.outTemperature.HasValue) { data.outTemperature = w.Value; } break; case "outhumidity": if (!data.outHumidity.HasValue) { data.outHumidity = w.Value; } break; case "pressure": if (!data.pressure.HasValue) { data.pressure = w.Value; } break; case "pressuretrend": if (data.pressureTrend == null) { data.pressureTrend = w.Values; } break; case "winddirection": if (!data.windDirection.HasValue) { data.windDirection = w.Value; } break; case "windspeed": if (!data.windSpeed.HasValue) { data.windSpeed = w.Value; } break; case "raintotal": if (!data.rainTotal.HasValue) { data.rainTotal = w.Value; } break; case "raintotaltrend": if (data.rainTotalTrend == null) { data.rainTotalTrend = w.Values; } break; } } // display the data if (data.outTemperature.HasValue) { point.X = padding; point.Y = (rowheight * 1); Canvas.Text(RGBA.White, point, $"current: {data.outTemperature:f0}°", fontsize, fontname); } if (data.outHumidity.HasValue) { point.X = padding; point.Y = (rowheight * 2); Canvas.Text(RGBA.White, point, $"humidity: {data.outHumidity:f0}%", fontsize, fontname); } if (data.pressure.HasValue) { point.X = padding; point.Y = (rowheight * 3); Canvas.Text(RGBA.White, point, $"pressure: {data.pressure:f2} inHg", fontsize, fontname); if (data.pressureTrend != null) { point.X = padding; point.Y = (rowheight * 4); var trend = ReadPressureTrend(data.pressure.Value, data.pressureTrend); var change = trend.Item2 == PressureChange.Failing ? "↓" : (trend.Item2 == PressureChange.Rising ? "↑" : "-"); Canvas.Text(RGBA.White, point, $" {trend.Item3} {change}", fontsize, fontname); } } if (data.windDirection.HasValue) { point.X = padding; point.Y = (rowheight * 5); Canvas.Text(RGBA.White, point, $"wind: {DegreesToCompass(data.windDirection.Value)}", fontsize, fontname); } if (data.windSpeed.HasValue) { point.X = padding + (rowheight * 6); point.Y = (rowheight * 5); Canvas.Text(RGBA.White, point, $"{data.windSpeed:f0} mph", fontsize, fontname); } if (data.rainTotal.HasValue) { point.X = padding; point.Y = (rowheight * 6); var rainTotal = data.rainTotal; if (data.rainTotalTrend != null && data.rainTotalTrend.Length >= 1) { rainTotal -= data.rainTotalTrend[data.rainTotalTrend.Length - 1]; } Canvas.Text(RGBA.White, point, $"rain: {rainTotal:f2} in", fontsize, fontname); // debug if (true) { point.X = padding; point.Y = (rowheight * 7); Canvas.Text(RGBA.White, point, $"{data.utcDate.ToLocalTime():yyyy/MM/dd hh:mm}", fontsize * 0.5f, fontname); } } } } finally { await Canvas.ResumeLayout(); } // fire that the frame is done if (OnRendered != null) { OnRendered(); } // set state back to not running System.Threading.Volatile.Write(ref FrameLock, 0); }