internal static InvalidOperation Parse(XElement xe) { var result = new InvalidOperation { Record = int.Parse(xe.Attribute("record").Value), Call = ClublogCtyXml.GetString(xe, "call"), End = ClublogCtyXml.GetNullableDateTime(xe, "end"), Start = ClublogCtyXml.GetNullableDateTime(xe, "start"), }; return(result); }
public static ClublogCtyXml Parse(string xml) { var result = new ClublogCtyXml(); XDocument xDocument = XDocument.Parse(xml); result.Entities = Fetch(xDocument, "entities", "entity", (xe) => Entity.Parse(xe)); result.Exceptions = Fetch(xDocument, "exceptions", "exception", (xe) => ExceptionRecord.Parse(xe)); result.InvalidOperations = Fetch(xDocument, "invalid_operations", "invalid", (xe) => InvalidOperation.Parse(xe)); result.Prefixes = Fetch(xDocument, "prefixes", "prefix", (xe) => Prefix.Parse(xe)); result.ZoneExceptions = Fetch(xDocument, "zone_exceptions", "zone_exception", (xe) => ZoneException.Parse(xe)); result.Updated = DateTime.Parse(xDocument.Root.Attribute("date").Value); return(result); }
internal static Prefix Parse(XElement xe) { return(new Prefix { Record = int.Parse(xe.Attribute("record").Value), Call = ClublogCtyXml.GetString(xe, "call"), End = ClublogCtyXml.GetNullableDateTime(xe, "end"), Start = ClublogCtyXml.GetNullableDateTime(xe, "start"), Adif = ClublogCtyXml.GetNullableInt(xe, "adif"), Continent = ClublogCtyXml.GetString(xe, "cont"), CqZone = ClublogCtyXml.GetNullableInt(xe, "cqz"), Entity = ClublogCtyXml.GetString(xe, "entity"), Latitude = ClublogCtyXml.GetNullableDouble(xe, "lat"), Longitude = ClublogCtyXml.GetNullableDouble(xe, "long"), }); }
internal static Entity Parse(XElement xe) { var result = new Entity { Adif = int.Parse(ClublogCtyXml.GetString(xe, "adif")), Continent = ClublogCtyXml.GetString(xe, "cont"), CqZone = int.Parse(ClublogCtyXml.GetString(xe, "cqz")), Deleted = ClublogCtyXml.GetBool(xe, "deleted"), End = ClublogCtyXml.GetNullableDateTime(xe, "end"), Start = ClublogCtyXml.GetNullableDateTime(xe, "start"), Latitude = double.Parse(ClublogCtyXml.GetString(xe, "lat")), Longitude = double.Parse(ClublogCtyXml.GetString(xe, "long")), Name = ClublogCtyXml.GetString(xe, "name"), Prefix = ClublogCtyXml.GetString(xe, "prefix"), Whitelist = ClublogCtyXml.GetNullableBool(xe, "whitelist"), WhitelistEnd = ClublogCtyXml.GetNullableDateTime(xe, "whitelist_end"), WhitelistStart = ClublogCtyXml.GetNullableDateTime(xe, "whitelist_start"), }; return(result); }
static void Main(string[] args) { bool all = args.Any(a => a == "--all"); bool grids = args.Any(a => a == "--grids"); string bandArg = args.SingleOrDefault(a => a.EndsWith("m")); if (string.IsNullOrWhiteSpace(bandArg) || !int.TryParse(bandArg.Substring(0, bandArg.Length - 1).Replace("--", ""), out int band)) { band = 20; } Console.WriteLine($"Selected {band}m, specify (e.g.) --6m for another band"); if (!all) { Console.WriteLine("Only showing needed spots. Pass --all for all spots."); } if (!grids) { Console.WriteLine("Not looking for unworked grids. Pass --grids to turn this on."); } if (args.Any(a => a == "--help" || a == "-h" || a == "/?")) { Console.WriteLine(@"A work in progress, that listens to udp://localhost:2237 for WSJT-X, works out the DXCC entity of every call heard using Clublog's cty.xml, then queries a Cloudlog instance via its API to see if it's a needed slot. If it is, it highlights the call in red in the console window."); return; } if (!File.Exists(configFile) || File.ReadAllText(configFile).Contains(connectionStringKey)) { Console.WriteLine("You need to provide a Cloudlog URL, e.g. https://mycloudloginstance.net"); Console.WriteLine("in order for ft8spotter to check spots against Cloudlog. Please provide it now..."); string url = Console.ReadLine(); string dir = Path.GetDirectoryName(configFile); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } File.WriteAllText(configFile, $"{urlKey}={url}"); } var config = GetConfig(); cloudLogUri = new Uri(new Uri(config[urlKey]), "index.php/api/"); var fi = new FileInfo("cty.xml"); bool isFresh = false; if (DateTime.Now - fi.LastWriteTime > TimeSpan.FromDays(1)) { var wc = new WebClient(); wc.DownloadFile("https://cdn.clublog.org/cty.php?api=a11c3235cd74b88212ce726857056939d52372bd&zip=1", "cty_new.xml.zip"); if (File.Exists("cty.xml.bak")) { File.Delete("cty.xml.bak"); } File.Move("cty.xml", "cty.xml.bak"); ZipFile.ExtractToDirectory("cty_new.xml.zip", "."); isFresh = true; File.Delete("cty_new.xml.zip"); } try { ctyXml = ClublogCtyXml.Parse(File.ReadAllText("cty.xml")); } catch (Exception ex) { if (isFresh) { File.Delete("cty.xml"); File.Move("cty.xml.bak", "cty.xml"); Console.WriteLine("Failed to update cty.xml"); ctyXml = ClublogCtyXml.Parse(File.ReadAllText("cty.xml")); } } const int port = 2237; using (var client = new UdpClient(port, AddressFamily.InterNetwork)) { Console.WriteLine($"Listening for WSJT-X on UDP port {port}"); var sw = Stopwatch.StartNew(); while (true) { var ipep = new IPEndPoint(IPAddress.Loopback, 0); byte[] msg = client.Receive(ref ipep); if (ParseResult.Success != DecodeMessage.TryParse(msg, out DecodeMessage decodeMessage)) { continue; } //if (msg[11] == 0x02) //{ //string heardCall = GetHeardCall(msg); string heardCall = GetHeardCall(decodeMessage.Message); if (heardCall == null) { continue; } var entity = GetEntity(heardCall); string grid = GetGrid(msg); var needed = entity == null ? Needed.No : GetNeeded(band, entity.Adif, grids ? grid : null, "ft8"); if (all || !Needed.No.Equals(needed)) { if (sw.Elapsed > TimeSpan.FromSeconds(5)) { Console.WriteLine($"--- {DateTime.Now:HH:mm:ss} --------------------------"); sw.Restart(); } var colBefore = Console.ForegroundColor; if (needed.NewCountryOnAnyBand) { Console.ForegroundColor = ConsoleColor.Green; } else if (needed.NewCountryOnBand) { Console.ForegroundColor = ConsoleColor.Yellow; } else if (needed.NewCountryOnBandOnMode) { Console.ForegroundColor = ConsoleColor.DarkYellow; } else if (needed.NewGridOnAnyBand) { Console.ForegroundColor = ConsoleColor.Red; } else if (needed.NewGridOnBand) { Console.ForegroundColor = ConsoleColor.Magenta; } else if (needed.NewGridOnBandOnMode) { Console.ForegroundColor = ConsoleColor.DarkRed; } WriteAtColumn(0, needed, 19); WriteAtColumn(19, heardCall, 10); WriteAtColumn(30, decodeMessage.Snr, 4); WriteAtColumn(34, IsGrid(grid) ? grid : String.Empty, 4); WriteAtColumn(39, entity?.Adif, 3); WriteAtColumn(43, (entity?.Entity) ?? "Unknown", 50); Console.WriteLine(); Console.ForegroundColor = colBefore; } } } }