using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; using BlubbFish.IoT.Pocsag.BosServerDatatypes.Mqtt; using BlubbFish.IoT.Pocsag.BosServerDatatypes.Json; using BlubbFish.Utils; using BlubbFish.Utils.IoT.Bots; using BlubbFish.Utils.IoT.Connector; using BlubbFish.Utils.IoT.Events; namespace BlubbFish.IoT.Pocsag.BosServerParser { class Program : ABot { private readonly ABackend bmqtt; private readonly ABackend bjson; private readonly Dictionary bosconf; static void Main(String[] args) => new Program(args, true, "bsparser"); public Program(String[] args, Boolean fileLogging, String configSearchPath) : base(args, fileLogging, configSearchPath) { this.bmqtt = ABackend.GetInstance(InIReader.GetInstance("settings").GetSection("backend")); this.bjson = ABackend.GetStorageInstance(InIReader.GetInstance("settings").GetSection("storage"),new List { typeof(RicData) }); this.bosconf = InIReader.GetInstance("settings").GetSection("bosserverparser"); this.bmqtt.MessageIncomming += this.Mqtt_MessageIncomming; this.bmqtt.MessageSending += this.Mqtt_MessageSending; this.SendMqtt(new Message("Anwendung BosServerParser Version " + Assembly.GetEntryAssembly().GetCustomAttribute().InformationalVersion + " gestartet.")); this.WaitForShutdown(); this.SendMqtt(new Message("Anwendung BosServerParser wurde beendet... Ob das so soll?")); this.Dispose(); } private void Mqtt_MessageIncomming(Object sender, BackendEvent mqtt) { try { Console.WriteLine("<= MQTT [" + mqtt.From.ToString() + "]: " + mqtt.Message); if(AMqttMessage.CheckJson(mqtt.Message, typeof(PocsagHttp))) { PocsagHttp p = PocsagHttp.ConvertJson(mqtt.Message); String funktion = this.ParseFunction(p.Function); (String name, RicDescription ric) = this.ParseRic(p.Address); GeoData geo = this.ParseLocation(p.Message); Boolean sendonline = this.ParseFilter(p.Message, ric, p.Address); Boolean isprivate = this.ParsePrivate(p.Address); this.SendMqtt(new PocsagParsed(p, funktion, name, ric, geo, sendonline, isprivate)); } else if(AMqttMessage.CheckJson(mqtt.Message, typeof(AddFilter))) { AddFilter filter = AddFilter.ConvertJson(mqtt.Message); if(this.InsertFilter(filter)) { this.SendMqtt(new Message("Hallo " + filter.Sender + ", die RIC " + filter.Ric + " wurde als \"" + filter.Task + "\" geflaggt, Nachrichten werden zukünftig gefiltert.")); } else { this.SendMqtt(new Message("Hallo " + filter.Sender + ", das hinzufügen des Filters \"" + filter.Task + "\" für die RIC " + filter.Ric + " ist fehlgeschlagen.")); } } } catch(Exception ex) { Helper.WriteError("Backend_MessageIncomming(): " + ex.Message + "\n\n" + ex.StackTrace); } } private void Mqtt_MessageSending(Object sender, BackendEvent mqtt) { try { Console.WriteLine("=> MQTT [" + mqtt.From.ToString() + "]: " + mqtt.Message); } catch(Exception ex) { Helper.WriteError("Backend_MessageSending(): " + ex.Message + "\n\n" + ex.StackTrace); } } private void SendMqtt(AMqttMessage msg) { try { ((Utils.IoT.Connector.Data.Mqtt)this.bmqtt).Send(this.bosconf["topic"] + "/" + msg.Datatype, msg.ToJson()); } catch(Exception e) { Helper.WriteError("SendMqtt(): " + e.Message + "\n\n" + e.StackTrace); } } private String ParseFunction(String function) => function switch { "a" => "EIL", "b" => "ZEIT", "c" => "PROBE", "d" => "ENDE", _ => "" }; private GeoData ParseLocation(String message) { Match m = Regex.Match(message, @"#C(?.+?),(?.+?)#"); if(m.Success) { if(Double.TryParse(m.Groups["lat"].Value.Insert(2, "."), NumberStyles.Float, CultureInfo.InvariantCulture, out Double lat) && Double.TryParse(m.Groups["lon"].Value.Insert(2, "."), NumberStyles.Float, CultureInfo.InvariantCulture, out Double lon)) { return new GeoData(lat, lon); } } return null; } private (String, RicDescription) ParseRic(String ric) { RicData ric_data = ((Utils.IoT.Connector.Storage.Json)this.bjson).Get(ric); RicDescription desc = null; String text; if(ric_data is null) { text = ric; } else { desc = new RicDescription(ric, ric_data.Location, ric_data.ShortDescription, ric_data.LongDescription); List text_parts = new List(); if(!(ric_data.Location is null) && ric_data.Location != "") { text_parts.Add(ric_data.Location); } if(!(ric_data.ShortDescription is null) && ric_data.ShortDescription != "") { text_parts.Add(ric_data.ShortDescription); } if(!(ric_data.LongDescription is null) && ric_data.LongDescription != "") { text_parts.Add("(" + ric_data.LongDescription + ")"); } text = String.Join(" ", text_parts); } return (text, desc); } private Boolean ParseFilter(String message, RicDescription ric, String address) { if(ric != null && ric.LongDescription.ToLower() == "idea") { return false; } else if(ric != null && ric.LongDescription.ToLower() == "leer") { return false; } else if(message == "" && ric is null) { return false; } foreach(KeyValuePair item in InIReader.GetInstance("settings").GetSection("filter")) { String[] a = item.Value.Split("|"); switch(a[0]) { case "address": if(address.StartsWith(a[1])) { return false; } break; case "message": if(message == a[1]) { return false; } break; } } return true; } private Boolean ParsePrivate(String address) => this.bosconf["special-ric"].Split(";").Contains(address); private Boolean InsertFilter(AddFilter filter) { try { return ((Utils.IoT.Connector.Storage.Json)this.bjson).Put(new RicData("", "BosServer", filter.Task.ToUpper()), filter.Ric); } catch { Helper.WriteError("=> Database Filter [" + filter.Ric + "*] " + filter.Task + " konnte nicht hinzugefügt werden!"); } return false; } public override void Dispose() { if(this.bmqtt != null) { this.bmqtt.Dispose(); } if(this.bjson != null) { this.bjson.Dispose(); } base.Dispose(); } } }