BosServer/BosServerParser/Program.cs
2026-08-02 23:33:31 +02:00

171 lines
6.8 KiB
C#

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<String, String> 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<Type> { 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<AssemblyInformationalVersionAttribute>().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(?<lon>.+?),(?<lat>.+?)#");
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<RicData>)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<String> text_parts = new List<String>();
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<String, String> 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<RicData>)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();
}
}
}