diff --git a/Lora-Map/Model/Admin/AdminModel.cs b/Lora-Map/Model/Admin/AdminModel.cs index 8271e94..8acaf8f 100644 --- a/Lora-Map/Model/Admin/AdminModel.cs +++ b/Lora-Map/Model/Admin/AdminModel.cs @@ -2,10 +2,13 @@ using System.Collections.Generic; using System.IO; using System.Net; +using System.Text; using BlubbFish.Utils; using BlubbFish.Utils.IoT.Bots; +using Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects; + using LitJson; namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin { @@ -52,27 +55,33 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin { } } Console.WriteLine("200 - Send names.json " + cont.Request.Url.PathAndQuery); - return Webserver.SendJsonResponse(ret, cont); + return cont.SendStringResponse(JsonMapper.ToJson(ret)); } } else if(cont.Request.HttpMethod == "PUT") { if(cont.Request.Url.AbsolutePath.Length > 16) { String part = cont.Request.Url.AbsolutePath[16..]; if(this.datastorage.ContainsKey(part)) { - return this.SetJsonFile(cont, "json/" + this.datastorage[part].Item1 + ".json", this.datastorage[part].Item2); + return this.SetJsonFile(cont, part); } } } } - return Webserver.SendFileResponse(cont); + return cont.SendFileResponse(); } - private Boolean SetJsonFile(HttpListenerContext cont, String filename, String updatenotifier) { + private Boolean SetJsonFile(HttpListenerContext cont, String part) { StreamReader reader = new StreamReader(cont.Request.InputStream, cont.Request.ContentEncoding); + String filename = "json/" + this.datastorage[part].Item1 + ".json"; String rawData = reader.ReadToEnd(); cont.Request.InputStream.Close(); reader.Close(); try { - _ = JsonMapper.ToObject(rawData); + JsonData json = JsonMapper.ToObject(rawData); + if(part == "name") { + if(!NamesModel.CheckJson(json)) { + throw new Exception("Check against model failed."); + } + } } catch (Exception) { Helper.WriteError("501 - Error recieving " + filename + ", no valid json " + cont.Request.Url.PathAndQuery); cont.Response.StatusCode = 501; @@ -80,12 +89,12 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin { } File.WriteAllText(filename, rawData); Console.WriteLine("200 - PUT " + filename + " " + cont.Request.Url.PathAndQuery); - this.GetEvent(updatenotifier)?.Invoke(this, new EventArgs()); + this.GetEvent(this.datastorage[part].Item2)?.Invoke(this, new EventArgs()); return true; } private Boolean Login(HttpListenerContext cont) { - Dictionary POST = Webserver.GetPostParams(cont.Request); + Dictionary POST = cont.Request.GetPostParams(); if(POST.ContainsKey("user") && POST["user"] == this.settings["admin_user"] && POST.ContainsKey("pass") && POST["pass"] == this.settings["admin_pass"]) { Int64 sessionid; while(true) { diff --git a/Lora-Map/Model/JsonObjects/LoraData.cs b/Lora-Map/Model/JsonObjects/LoraData.cs new file mode 100644 index 0000000..8cf32c8 --- /dev/null +++ b/Lora-Map/Model/JsonObjects/LoraData.cs @@ -0,0 +1,99 @@ +using System; +using System.Globalization; + +using LitJson; + +namespace Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects { + public class LoraData { + #region mandatory field + public Double BatteryLevel { + get; + } + public Boolean CorrectInterface { + get; + } + public LoraDataGps Gps { + get; + } + public String Hash { + get; + } + public String Name { + get; + } + #endregion + + #region optional field + public DateTime Receivedtime { + get; + } + public Double Rssi { + get; + } + public Double Snr { + get; + } + #endregion + + + public static Boolean CheckJson(JsonData json) => + json.ContainsKey("BatteryLevel") && (json["BatteryLevel"].IsDouble || json["BatteryLevel"].IsInt) + && json.ContainsKey("CorrectInterface") && json["CorrectInterface"].IsBoolean + && json.ContainsKey("Gps") && json["Gps"].IsObject + && LoraDataGps.CheckJson(json["Gps"]) + && json.ContainsKey("Hash") && json["Hash"].IsString + && json.ContainsKey("Name") && json["Name"].IsString; + + public LoraData(JsonData json) { + //mandatory field + this.BatteryLevel = json["BatteryLevel"].IsInt ? (Int32)json["BatteryLevel"] : (Double)json["BatteryLevel"]; + this.CorrectInterface = (Boolean)json["CorrectInterface"]; + this.Gps = new LoraDataGps(json["Gps"]); + this.Hash = (String)json["Hash"]; + this.Name = (String)json["Name"]; + //optional field + this.Rssi = json.ContainsKey("Rssi") && (json["Rssi"].IsDouble || json["Rssi"].IsInt) ? json["Rssi"].IsInt ? (Int32)json["Rssi"] : (Double)json["Rssi"] : 0; + this.Snr = json.ContainsKey("Snr") && (json["Snr"].IsDouble || json["Snr"].IsInt) ? json["Snr"].IsInt ? (Int32)json["Snr"] : (Double)json["Snr"] : 0; + this.Receivedtime = json.ContainsKey("Receivedtime") && json["Receivedtime"].IsString && DateTime.TryParse((String)json["Receivedtime"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime) ? updatetime.ToUniversalTime() : DateTime.UtcNow; + } + } + + public class LoraDataGps { + #region mandatory field + public Double Latitude { + get; + } + public Double Longitude { + get; + } + public Boolean Fix { + get; + } + public Double Height { + get; + } + #endregion + + #region optional field + public Double Hdop { + get; + } + #endregion + + public static Boolean CheckJson(JsonData json) => + json.ContainsKey("Latitude") && (json["Latitude"].IsDouble || json["Latitude"].IsInt) + && json.ContainsKey("Longitude") && (json["Longitude"].IsDouble || json["Longitude"].IsInt) + && json.ContainsKey("Fix") && json["Fix"].IsBoolean + && json.ContainsKey("Height") && (json["Height"].IsDouble || json["Height"].IsInt); + + public LoraDataGps(JsonData json) { + //mandatory field + this.Latitude = json["Latitude"].IsInt ? (Int32)json["Latitude"] : (Double)json["Latitude"]; + this.Longitude = json["Longitude"].IsInt ? (Int32)json["Longitude"] : (Double)json["Longitude"]; + this.Fix = (Boolean)json["Fix"]; + this.Height = json["Height"].IsInt ? (Int32)json["Height"] : (Double)json["Height"]; + //optional field + this.Hdop = json.ContainsKey("Hdop") && (json["Hdop"].IsDouble || json["Hdop"].IsInt) ? json["Hdop"].IsInt ? (Int32)json["Hdop"] : (Double)json["Hdop"] : 0; + } + } +} diff --git a/Lora-Map/Model/JsonObjects/NamesModel.cs b/Lora-Map/Model/JsonObjects/NamesModel.cs new file mode 100644 index 0000000..7380356 --- /dev/null +++ b/Lora-Map/Model/JsonObjects/NamesModel.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.IO; + +using BlubbFish.Utils; + +using LitJson; + +namespace Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects { + public class NamesModel { + public SortedDictionary Items { + get; + } + + public static Boolean CheckJson(JsonData json) { + if(!json.IsObject) { + return false; + } + foreach(String item in json.Keys) { + if(!NamesModelData.CheckJson(json[item])) { + return false; + } + } + return true; + } + + public NamesModel() { + this.Items = new SortedDictionary(); + JsonData json = this.LoadFromFile(); + if(json != null && CheckJson(json)) { + foreach(String item in json.Keys) { + this.Items.Add(item, new NamesModelData(json[item])); + } + } + } + + private JsonData LoadFromFile() { + try { + if(!Directory.Exists("json")) { + _ = Directory.CreateDirectory("json"); + } + if(!File.Exists("json/names.json")) { + File.WriteAllText("json/names.json", "{}"); + } + return JsonMapper.ToObject(File.ReadAllText("json/names.json")); + } catch { + Helper.WriteError("Could not load json/names.json"); + return null; + } + } + } + + public class NamesModelData { + #region mandatory field + public String Name { + get; + } + public String Group { + get; + } + #endregion + + #region optional field + public String Icon { + get; + } + public NamesModelDataMarkerSvg MarkerSvg { + get; + } + #endregion + + public static Boolean CheckJson(JsonData json) => + json.ContainsKey("name") && json["name"].IsString + && json.ContainsKey("Group") && json["Group"].IsString; + + public NamesModelData(JsonData json) { + //mandatory field + this.Name = (String)json["name"]; + this.Group = (String)json["Group"]; + //optional field + this.MarkerSvg = json.ContainsKey("marker.svg") && json["marker.svg"].IsObject && NamesModelDataMarkerSvg.CheckJson(json["marker.svg"]) ? new NamesModelDataMarkerSvg(json["marker.svg"]) : null; + this.Icon = json.ContainsKey("icon") && json["icon"].IsString ? (String)json["icon"] : null; + } + } + + public class NamesModelDataMarkerSvg { + #region optional field + public NamesModelDataMarkerSvgPerson Person { + get; + } + #endregion + + public static Boolean CheckJson(JsonData json) => + json.ContainsKey("person") && json["person"].IsObject; + + public NamesModelDataMarkerSvg(JsonData json) { + //optional field + #pragma warning disable IDE0021 // Ausdruckskörper für Konstruktoren verwenden + this.Person = json.ContainsKey("person") && json["person"].IsObject && NamesModelDataMarkerSvgPerson.CheckJson(json["person"]) ? new NamesModelDataMarkerSvgPerson(json["person"]) : null; + #pragma warning restore IDE0021 // Ausdruckskörper für Konstruktoren verwenden + } + } + + public class NamesModelDataMarkerSvgPerson { + #region mandatory field + public String Funktion { + get; + } + public String Organisation { + get; + } + public String Rang { + get; + } + #endregion + + #region optional field + public String Text { + get; + } + public List Typ { + get; + } + + #endregion + public static Boolean CheckJson(JsonData json) => + json.ContainsKey("org") && json["org"].IsString + && json.ContainsKey("funct") && json["funct"].IsString + && json.ContainsKey("rang") && json["rang"].IsString; + + public NamesModelDataMarkerSvgPerson(JsonData json) { + //mandatory field + this.Organisation = (String)json["org"]; + this.Funktion = (String)json["funct"]; + this.Rang = (String)json["rang"]; + //optional field + this.Text = json.ContainsKey("text") && json["text"].IsString ? (String)json["text"] : null; + List typs = new List(); + if(json.ContainsKey("typ") && json["typ"].IsArray) { + foreach(JsonData item in json["typ"]) { + if(item.IsString) { + typs.Add(item.ToString()); + } + } + } + this.Typ = typs; + } + } +} diff --git a/Lora-Map/Model/Position/PositionAlarm.cs b/Lora-Map/Model/Position/PositionAlarm.cs index c5b8db4..71d2565 100644 --- a/Lora-Map/Model/Position/PositionAlarm.cs +++ b/Lora-Map/Model/Position/PositionAlarm.cs @@ -1,7 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using LitJson; + +using Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects; namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position { public class PositionAlarm : PositionItem { @@ -9,24 +10,21 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position { public List ButtonPressed => this.buttonhistory.Keys.ToList(); - public PositionAlarm(JsonData json) : base(json, null) { + public PositionAlarm(LoraData data) : base(data, null) { } - public override void Update(JsonData json) { - base.Update(json); - this.SetHistory(json); + public override void Update(LoraData data) { + base.Update(data); + this.SetHistory(data); } - private void SetHistory(JsonData json) { - if(json.ContainsKey("Hash") && json["Hash"].IsString) { - String key = json["Hash"].ToString(); - if(!this.buttonhistory.ContainsValue(key)) { - this.buttonhistory.Add(DateTime.UtcNow, key); - if(this.buttonhistory.Count > 10) { - _ = this.buttonhistory.Remove(this.buttonhistory.Keys.ToList().First()); - } + private void SetHistory(LoraData data) { + if(!this.buttonhistory.ContainsValue(data.Hash)) { + this.buttonhistory.Add(DateTime.UtcNow, data.Hash); + if(this.buttonhistory.Count > 10) { + _ = this.buttonhistory.Remove(this.buttonhistory.Keys.ToList().First()); } - } - } + } + } } } diff --git a/Lora-Map/Model/Position/PositionItem.cs b/Lora-Map/Model/Position/PositionItem.cs index 0c45c72..de3ecf9 100644 --- a/Lora-Map/Model/Position/PositionItem.cs +++ b/Lora-Map/Model/Position/PositionItem.cs @@ -1,14 +1,17 @@ using System; -using System.Globalization; +using System.Collections.Generic; +using System.Linq; +using Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects; using Fraunhofer.Fit.IoT.LoraMap.Model.Svg; -using LitJson; - namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position { public class PositionItem { private Double _lastLat = 0; private Double _lastLon = 0; + private readonly SortedDictionary _history = new SortedDictionary(); + private String _lastHash = ""; + private Boolean _isdublicate = false; public Double Rssi { get; private set; } public Double Snr { get; private set; } @@ -27,19 +30,20 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position { public String Icon { get; private set; } public String MenuIcon { get; private set; } public String Group { get; private set; } + public List History => this._history.Values.ToList(); - public PositionItem(JsonData json, JsonData marker) { - this.Update(json); - this.UpdateMarker(marker, GetId(json)); + public PositionItem(LoraData data, NamesModel marker) { + this.Update(data); + this.UpdateMarker(marker, data.Name); } - public void UpdateMarker(JsonData marker, String id) { - if(marker != null && marker.ContainsKey(id)) { - this.Name = marker[id].ContainsKey("name") && marker[id]["name"].IsString ? (String)marker[id]["name"] : id; - Tuple icons = this.ParseIconConfig(marker[id]); + public void UpdateMarker(NamesModel marker, String id) { + if(marker.Items.ContainsKey(id)) { + this.Name = marker.Items[id].Name; + Tuple icons = this.ParseIconConfig(marker.Items[id]); this.Icon = icons.Item1; this.MenuIcon = icons.Item2; - this.Group = marker[id].ContainsKey("Group") && marker[id]["Group"].IsString ? (String)marker[id]["Group"] : "no"; + this.Group = marker.Items[id].Group; } else { this.Name = id; this.Icon = null; @@ -47,44 +51,43 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position { } } - private Tuple ParseIconConfig(JsonData marker) { + private Tuple ParseIconConfig(NamesModelData marker) { String icon = null; String menu = null; - if(marker.ContainsKey("marker.svg") && marker["marker.svg"].IsObject) { - icon = SVGMarker.ParseConfig(marker["marker.svg"], this.Name); - if(marker["marker.svg"].ContainsKey("person") && marker["marker.svg"]["person"].IsObject) { - menu = SVGPerson.ParseConfig(marker["marker.svg"]["person"]); + if(marker.MarkerSvg != null) { + icon = SVGMarker.ParseConfig(marker.MarkerSvg, this.Name); + if(marker.MarkerSvg.Person != null) { + menu = SVGPerson.ParseConfig(marker.MarkerSvg.Person); } - } else if(marker.ContainsKey("icon") && marker["icon"].IsString) { - icon = (String)marker["icon"]; + } else if(marker.Icon != null) { + icon = marker.Icon; } return new Tuple(icon, menu); } - public static Boolean CheckJson(JsonData json) => - json.ContainsKey("BatteryLevel") && (json["BatteryLevel"].IsDouble || json["BatteryLevel"].IsInt) - && json.ContainsKey("Gps") && json["Gps"].IsObject - && json["Gps"].ContainsKey("Latitude") && (json["Gps"]["Latitude"].IsDouble || json["Gps"]["Latitude"].IsInt) - && json["Gps"].ContainsKey("Longitude") && (json["Gps"]["Longitude"].IsDouble || json["Gps"]["Longitude"].IsInt) - && json["Gps"].ContainsKey("Fix") && json["Gps"]["Fix"].IsBoolean - && json["Gps"].ContainsKey("Height") && (json["Gps"]["Height"].IsDouble || json["Gps"]["Height"].IsInt) - && json.ContainsKey("Name") && json["Name"].IsString; - - public static String GetId(JsonData json) => (String)json["Name"]; - - public virtual void Update(JsonData json) { - this.Rssi = json.ContainsKey("Rssi") && (json["Rssi"].IsDouble || json["Rssi"].IsInt) && Double.TryParse(json["Rssi"].ToString(), out Double rssi) ? rssi : 0; - this.Snr = json.ContainsKey("Snr") && (json["Snr"].IsDouble || json["Snr"].IsInt) && Double.TryParse(json["Snr"].ToString(), out Double snr) ? snr : 0; - this.Lorarecievedtime = json.ContainsKey("Receivedtime") && json["Receivedtime"].IsString && DateTime.TryParse((String)json["Receivedtime"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime) ? updatetime.ToUniversalTime() : DateTime.UtcNow; + public virtual void Update(LoraData data) { + this._isdublicate = false; + if(data.Hash == this._lastHash) { + if(!data.CorrectInterface) { + Console.WriteLine("dublicate-Paket, reomove wrong reciever!"); + return; + } + this._isdublicate = true; + Console.WriteLine("dublicate-Paket!"); + } + this._lastHash = data.Hash; + this.Rssi = data.Rssi; + this.Snr = data.Snr; + this.Lorarecievedtime = data.Receivedtime; this.Recievedtime = DateTime.UtcNow; - this.Battery = Math.Round(json["BatteryLevel"].IsInt ? (Int32)json["BatteryLevel"] : (Double)json["BatteryLevel"], 2); + this.Battery = Math.Round(data.BatteryLevel, 2); this.Batterysimple = this.Battery < 3.44 ? 0 : this.Battery < 3.53 ? 1 : this.Battery < 3.6525 ? 2 : this.Battery < 3.8825 ? 3 : 4; - this.Latitude = json["Gps"]["Latitude"].IsInt ? (Int32)json["Gps"]["Latitude"] : (Double)json["Gps"]["Latitude"]; - this.Longitude = json["Gps"]["Longitude"].IsInt ? (Int32)json["Gps"]["Longitude"] : (Double)json["Gps"]["Longitude"]; - this.Fix = (Boolean)json["Gps"]["Fix"]; - this.Height = json["Gps"]["Height"].IsInt ? (Int32)json["Gps"]["Height"] : (Double)json["Gps"]["Height"]; - this.Hdop = json["Gps"].ContainsKey("Hdop") && (json["Gps"]["Hdop"].IsDouble || json["Gps"]["Hdop"].IsInt) && Double.TryParse(json["Gps"]["Hdop"].ToString(), out Double hdop) ? hdop : 0; + this.Latitude = data.Gps.Latitude; + this.Longitude = data.Gps.Longitude; + this.Fix = data.Gps.Fix; + this.Height = data.Gps.Height; + this.Hdop = data.Gps.Hdop; if(!this.Fix) { this.Latitude = this._lastLat; @@ -93,10 +96,38 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position { this._lastLat = this.Latitude; this._lastLon = this.Longitude; this.Lastgpspostime = DateTime.UtcNow; + if(!this._isdublicate) { + this.StoreHistory(); + } } this.UTM = new UTMData(this.Latitude, this.Longitude); } - + private void StoreHistory() { + if(Settings.Instance.Internal.History.Enabled) { + if(Settings.Instance.Internal.History.Amount != 0 && this._history.Count > Settings.Instance.Internal.History.Amount) { + _ = this._history.Remove(this._history.Keys.ToList().First()); + } + if(Settings.Instance.Internal.History.Time != 0) { + List removeCandidates = new List(); + DateTime now = DateTime.UtcNow; + foreach(KeyValuePair item in this._history) { + if((now - item.Key).TotalSeconds > Settings.Instance.Internal.History.Time) { + removeCandidates.Add(item.Key); + } + } + if(removeCandidates.Count > 0) { + foreach(DateTime item in removeCandidates) { + _ = this._history.Remove(item); + } + } + } + if(!this._history.ContainsKey(this.Recievedtime)) { + this._history.Add(this.Recievedtime, new Double[] { this.Latitude, this.Longitude }); + } + } else { + this._history.Clear(); + } + } } } diff --git a/Lora-Map/Model/Position/PositionModel.cs b/Lora-Map/Model/Position/PositionModel.cs index 35ffc85..a19f707 100644 --- a/Lora-Map/Model/Position/PositionModel.cs +++ b/Lora-Map/Model/Position/PositionModel.cs @@ -1,16 +1,17 @@ using System; using System.Collections.Generic; -using System.IO; using BlubbFish.Utils; +using Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects; + using LitJson; namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position { public class PositionModel : OwnSingeton { private readonly Object lockData = new Object(); - private readonly Object lockPanic = new Object(); - private JsonData marker; + private readonly Object lockAlarm = new Object(); + private NamesModel marker; public SortedDictionary Positions { get; private set; @@ -23,27 +24,25 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position { protected PositionModel() { this.Positions = new SortedDictionary(); this.Alarms = new SortedDictionary(); - this.CheckJsonFile(); - this.marker = JsonMapper.ToObject(File.ReadAllText("json/names.json")); - + this.marker = new NamesModel(); } public void ParseMqttJson(JsonData mqtt, String from) { - if((from.Contains("lora/data") || from.Contains("lora/panic")) && PositionItem.CheckJson(mqtt)) { - String name = PositionItem.GetId(mqtt); + if((from.Contains("lora/data") || from.Contains("lora/panic")) && LoraData.CheckJson(mqtt)) { + LoraData data = new LoraData(mqtt); lock(this.lockData) { - if(this.Positions.ContainsKey(name)) { - this.Positions[name].Update(mqtt); + if(this.Positions.ContainsKey(data.Name)) { + this.Positions[data.Name].Update(data); } else { - this.Positions.Add(name, new PositionItem(mqtt, this.marker)); + this.Positions.Add(data.Name, new PositionItem(data, this.marker)); } } if(from.Contains("lora/panic")) { - lock(this.lockPanic) { - if(this.Alarms.ContainsKey(name)) { - this.Alarms[name].Update(mqtt); + lock(this.lockAlarm) { + if(this.Alarms.ContainsKey(data.Name)) { + this.Alarms[data.Name].Update(data); } else { - this.Alarms.Add(name, new PositionAlarm(mqtt)); + this.Alarms.Add(data.Name, new PositionAlarm(data)); } } Console.WriteLine("PANIC erhalten!"); @@ -53,21 +52,11 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position { } public void ReloadNames(Object sender, EventArgs e) { - this.CheckJsonFile(); - this.marker = JsonMapper.ToObject(File.ReadAllText("json/names.json")); + this.marker = new NamesModel(); foreach(KeyValuePair item in this.Positions) { item.Value.UpdateMarker(this.marker, item.Key); } Console.WriteLine("Namen und Icons aktualisiert!"); } - - private void CheckJsonFile() { - if(!Directory.Exists("json")) { - _ = Directory.CreateDirectory("json"); - } - if(!File.Exists("json/names.json")) { - File.WriteAllText("json/names.json", "{}"); - } - } } } diff --git a/Lora-Map/Model/Svg/SVGMarker.cs b/Lora-Map/Model/Svg/SVGMarker.cs index 2125eda..5507839 100644 --- a/Lora-Map/Model/Svg/SVGMarker.cs +++ b/Lora-Map/Model/Svg/SVGMarker.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; +using System.Web; -using LitJson; +using Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects; namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { public class SVGMarker : SVGFile { @@ -12,7 +12,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { public SVGMarker(String query) : base(query, 86, 121.25, new List() { 0, 0, 86, 121.25 }) => this.css.Add("#marker-name tspan {\n font-size: 20px;\n font-family: DIN1451;\n}"); - public static String ParseConfig(JsonData json, String name) => "api/svg/marker.svg" + DictionaryConfigToString(GenerateConfig(json, name)); + public static String ParseConfig(NamesModelDataMarkerSvg json, String name) => "api/svg/marker.svg" + DictionaryConfigToString(GenerateConfig(json, name)); protected override void ParseParams() { String[] parts = this.query.Split('&'); @@ -21,7 +21,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { if(keyvalue.Length == 2) { switch(keyvalue[0].ToLower()) { case "name": - this.name = keyvalue[1]; + this.name = HttpUtility.UrlDecode(keyvalue[1]); break; case "icon": this.icon = keyvalue[1].ToLower(); @@ -31,14 +31,14 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { } } - public static Dictionary GenerateConfig(JsonData json, String name) { - Dictionary config = new Dictionary(); + public static Dictionary> GenerateConfig(NamesModelDataMarkerSvg json, String name) { + Dictionary> config = new Dictionary>(); if(name != "") { - config.Add("name", name); + config.Add("name", new List() { name }); } - if(json.ContainsKey("person") && json["person"].IsObject) { - config.Add("icon", "person"); - Dictionary personconfig = SVGPerson.GenerateConfig(json["person"]); + if(json.Person != null) { + config.Add("icon", new List() { "person" }); + Dictionary> personconfig = SVGPerson.GenerateConfig(json.Person); personconfig.ToList().ForEach(x => config.Add(x.Key, x.Value)); } return config; @@ -52,7 +52,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { svg += "\n"; svg += "\n"; - svg += $"{this.name}\n"; + svg += $"{HttpUtility.HtmlEncode(this.name)}\n"; svg += "\n"; if(this.icon == "person") { diff --git a/Lora-Map/Model/Svg/SVGPerson.cs b/Lora-Map/Model/Svg/SVGPerson.cs index f2a6dac..ed795aa 100644 --- a/Lora-Map/Model/Svg/SVGPerson.cs +++ b/Lora-Map/Model/Svg/SVGPerson.cs @@ -2,8 +2,9 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Web; -using LitJson; +using Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects; namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { public class SVGPerson : SVGFile { @@ -11,7 +12,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { private String function; private String rang; private String text; - private String[] typs; + private readonly List typs = new List(); @@ -23,7 +24,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { this.css.Add("#person-layer-typ line {\n stroke-width: 3px;\n stroke: black;\n}"); } - public static String ParseConfig(JsonData json) => "api/svg/person.svg" + DictionaryConfigToString(GenerateConfig(json)); + public static String ParseConfig(NamesModelDataMarkerSvgPerson json) => "api/svg/person.svg" + DictionaryConfigToString(GenerateConfig(json)); protected override void ParseParams() { String[] parts = this.query.Split('&'); @@ -41,38 +42,27 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { this.rang = keyvalue[1].ToLower(); break; case "person-text": - this.text = keyvalue[1]; + this.text = HttpUtility.UrlDecode(keyvalue[1]); break; - case "person-typ": - this.typs = keyvalue[1].ToLower().Split(","); + case "person-typ[]": + this.typs.Add(HttpUtility.UrlDecode(keyvalue[1]).ToLower()); break; } } } } - public static Dictionary GenerateConfig(JsonData json) { - Dictionary config = new Dictionary(); - if(json.ContainsKey("org") && json["org"].IsString) { - config.Add("person-org", json["org"].ToString()); + public static Dictionary> GenerateConfig(NamesModelDataMarkerSvgPerson json) { + Dictionary> config = new Dictionary> { + { "person-org", new List() { json.Organisation } }, + { "person-funct", new List() { json.Funktion } }, + { "person-rang", new List() { json.Rang } } + }; + if(json.Text != null) { + config.Add("person-text", new List() { json.Text }); } - if(json.ContainsKey("funct") && json["funct"].IsString) { - config.Add("person-funct", json["funct"].ToString()); - } - if(json.ContainsKey("rang") && json["rang"].IsString) { - config.Add("person-rang", json["rang"].ToString()); - } - if(json.ContainsKey("text") && json["text"].IsString) { - config.Add("person-text", json["text"].ToString()); - } - if(json.ContainsKey("typ") && json["typ"].IsArray) { - List typs = new List(); - foreach(JsonData item in json["person"]["typ"]) { - if(item.IsString) { - typs.Add(item.ToString()); - } - } - config.Add("person-typ", String.Join(",", typs)); + if(json.Typ.Count > 0) { + config.Add("person-typ[]", json.Typ); } return config; } @@ -104,12 +94,11 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { svg += "\n"; svg += "\n"; } - if(this.text != null || this.typs != null && this.typs.All(x => this.typlookup.ContainsKey(x))) { + if(this.text != null || this.typs.Count > 0 && this.typs.All(x => this.typlookup.ContainsKey(x))) { svg += "\n"; - if(this.text != null && this.typs == null) { - svg += $"{this.text}\n"; - } - if(this.text == null && this.typs != null && this.typs.All(x => this.typlookup.ContainsKey(x))) { + if(this.text != null) { + svg += $"{HttpUtility.HtmlEncode(this.text)}\n"; + } else if(this.typs.Count > 0 && this.typs.All(x => this.typlookup.ContainsKey(x))) { foreach(String typ in this.typs) { svg += $"\n"; foreach(Tuple item in this.typlookup[typ].Lines) {