From 3705d78dcd7e3f10a38abb19e4de1531e320fdb9 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Sat, 10 Apr 2021 20:32:24 +0200 Subject: [PATCH] 1.3.1 Refactory is the king --- Lora-Map.sln | 14 +- Lora-Map/Lora-Map.csproj | 35 +- Lora-Map/Model/Admin/AdminModel.cs | 77 +- Lora-Map/Model/Admin/AdminSession.cs | 4 - .../{Camera.cs => Camera/CameraCounter.cs} | 8 +- .../{Crowd.cs => Camera/CameraDensity.cs} | 8 +- .../{Fight.cs => Camera/CameraFights.cs} | 6 +- Lora-Map/Model/Camera/CameraModel.cs | 62 ++ Lora-Map/Model/Marker.cs | 123 --- .../PositionAlarm.cs} | 6 +- Lora-Map/Model/{ => Position}/PositionItem.cs | 25 +- Lora-Map/Model/Position/PositionModel.cs | 73 ++ .../SensorEnviromentData.cs} | 6 +- Lora-Map/Model/Sensor/SensorModel.cs | 41 + .../SensorWeather.cs} | 17 +- Lora-Map/Model/Settings.cs | 219 ++++-- Lora-Map/Model/Svg/SVGFile.cs | 116 +++ Lora-Map/Model/Svg/SVGMarker.cs | 66 ++ Lora-Map/Model/Svg/SVGPerson.cs | 198 +++++ Lora-Map/Model/Svg/SvgModel.cs | 42 + Lora-Map/Server.cs | 216 +---- Lora-Map/resources/admin/index.html | 5 +- Lora-Map/resources/admin/js/adminmenu.js | 42 + Lora-Map/resources/admin/js/eximport.js | 56 ++ Lora-Map/resources/admin/js/menu.js | 741 ------------------ Lora-Map/resources/admin/js/nameseditor.js | 304 +++++++ Lora-Map/resources/admin/js/settings.js | 330 ++++++++ Lora-Map/resources/css/global.css | 2 +- Lora-Map/resources/js/functions.js | 111 +-- Lora-Map/resources/js/map.js | 280 +++---- Lora-Map/resources/js/marker.js | 101 +-- Lora-Map/resources/js/menu.js | 99 +-- Lora-Map/resources/js/overlays.js | 19 +- map-swagger.yml | 312 ++++++++ 34 files changed, 2292 insertions(+), 1472 deletions(-) rename Lora-Map/Model/{Camera.cs => Camera/CameraCounter.cs} (88%) rename Lora-Map/Model/{Crowd.cs => Camera/CameraDensity.cs} (92%) rename Lora-Map/Model/{Fight.cs => Camera/CameraFights.cs} (89%) create mode 100644 Lora-Map/Model/Camera/CameraModel.cs delete mode 100644 Lora-Map/Model/Marker.cs rename Lora-Map/Model/{AlarmItem.cs => Position/PositionAlarm.cs} (81%) rename Lora-Map/Model/{ => Position}/PositionItem.cs (80%) create mode 100644 Lora-Map/Model/Position/PositionModel.cs rename Lora-Map/Model/{EnviromentData.cs => Sensor/SensorEnviromentData.cs} (90%) create mode 100644 Lora-Map/Model/Sensor/SensorModel.cs rename Lora-Map/Model/{WeatherWarnings.cs => Sensor/SensorWeather.cs} (91%) create mode 100644 Lora-Map/Model/Svg/SVGFile.cs create mode 100644 Lora-Map/Model/Svg/SVGMarker.cs create mode 100644 Lora-Map/Model/Svg/SVGPerson.cs create mode 100644 Lora-Map/Model/Svg/SvgModel.cs create mode 100644 Lora-Map/resources/admin/js/adminmenu.js create mode 100644 Lora-Map/resources/admin/js/eximport.js delete mode 100644 Lora-Map/resources/admin/js/menu.js create mode 100644 Lora-Map/resources/admin/js/nameseditor.js create mode 100644 Lora-Map/resources/admin/js/settings.js create mode 100644 map-swagger.yml diff --git a/Lora-Map.sln b/Lora-Map.sln index 6999e79..c40d7cf 100644 --- a/Lora-Map.sln +++ b/Lora-Map.sln @@ -16,19 +16,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\update.sh = ..\update.sh EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bot-Utils_Core", "..\Utils\Bot-Utils\Bot-Utils\Bot-Utils_Core.csproj", "{ED37370F-AE65-498D-A425-413FEE69C0A8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bot-Utils", "..\Utils\Bot-Utils\Bot-Utils\Bot-Utils.csproj", "{ED37370F-AE65-498D-A425-413FEE69C0A8}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils_Core", "..\Utils\Utils\Utils\Utils_Core.csproj", "{E8268FE5-D6F0-4805-9BDE-9DBC9CB517FF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils", "..\Utils\Utils\Utils\Utils.csproj", "{E8268FE5-D6F0-4805-9BDE-9DBC9CB517FF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils-IoT_Core", "..\Utils\Utils-IoT\Utils-IoT\Utils-IoT_Core.csproj", "{04CF6328-3976-44D3-9959-A3B1A2C5C45A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils-IoT", "..\Utils\Utils-IoT\Utils-IoT\Utils-IoT.csproj", "{04CF6328-3976-44D3-9959-A3B1A2C5C45A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConnectorDataMqtt_Core", "..\Utils\ConnectorDataMqtt\ConnectorDataMqtt\ConnectorDataMqtt_Core.csproj", "{E40D29CB-B499-4FA6-AEA1-18E8CEAA911B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConnectorDataMqtt", "..\Utils\ConnectorDataMqtt\ConnectorDataMqtt\ConnectorDataMqtt.csproj", "{E40D29CB-B499-4FA6-AEA1-18E8CEAA911B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "litjson_Core", "..\Librarys\litjson\litjson\litjson_Core.csproj", "{FFC66B7F-B4FB-4E42-B896-2C6772D899AA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "litjson", "..\Librarys\litjson\litjson\litjson.csproj", "{FFC66B7F-B4FB-4E42-B896-2C6772D899AA}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "M2Mqtt_Core", "..\Librarys\mqtt\M2Mqtt\M2Mqtt_Core.csproj", "{00C678EE-6BAA-4FCB-AAA5-7755E65C6CC5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "M2Mqtt", "..\Librarys\mqtt\M2Mqtt\M2Mqtt.csproj", "{00C678EE-6BAA-4FCB-AAA5-7755E65C6CC5}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoordinateSharp_Core", "..\Librarys\Coordinates\CoordinateSharp\CoordinateSharp_Core.csproj", "{D9D4C842-5818-4E96-9BFE-7ADFB4D811BA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoordinateSharp", "..\Librarys\Coordinates\CoordinateSharp\CoordinateSharp.csproj", "{D9D4C842-5818-4E96-9BFE-7ADFB4D811BA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Lora-Map/Lora-Map.csproj b/Lora-Map/Lora-Map.csproj index 272d2dd..b483541 100644 --- a/Lora-Map/Lora-Map.csproj +++ b/Lora-Map/Lora-Map.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.0 + netcoreapp3.1 Fraunhofer.Fit.IoT.LoraMap Lora-Map Adminrights.manifest @@ -10,15 +10,16 @@ Displays Items with Coordinates from Mqtt on a Map Fraunhofer FIT LoraMap.IoT.Fit.Fraunhofer - Copyright © Fraunhofer FIT, BlubbFish 2018 - 20.01.2020 + Copyright © Fraunhofer FIT, BlubbFish 2018 - 10.04.2021 BlubbFish - 1.3.0 + 1.3.1 LICENSE https://github.com/MONICA-Project/lora-map https://github.com/MONICA-Project/lora-map.git git de-DE + 1.3.1 Refactory is the king 1.3.0 New Gateway 1.2.10 Refactoring is the thing 1.2.9 The PüMa Release @@ -43,13 +44,13 @@ - - - - - - - + + + + + + + @@ -57,8 +58,9 @@ + - + @@ -71,7 +73,16 @@ PreserveNewest - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + PreserveNewest diff --git a/Lora-Map/Model/Admin/AdminModel.cs b/Lora-Map/Model/Admin/AdminModel.cs index 4c405b8..8271e94 100644 --- a/Lora-Map/Model/Admin/AdminModel.cs +++ b/Lora-Map/Model/Admin/AdminModel.cs @@ -2,17 +2,26 @@ using System.Collections.Generic; using System.IO; using System.Net; -using System.Text; + using BlubbFish.Utils; using BlubbFish.Utils.IoT.Bots; + using LitJson; namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin { class AdminModel { public delegate void AdminEvent(Object sender, EventArgs e); + #pragma warning disable 0067 public event AdminEvent NamesUpdate; public event AdminEvent GeoUpdate; public event AdminEvent SettingsUpdate; + #pragma warning restore 0067 + + private readonly SortedDictionary> datastorage = new SortedDictionary>() { + { "name", new Tuple("names", "NamesUpdate") }, + { "geo", new Tuple("geo", "GeoUpdate") }, + { "setting", new Tuple("settings", "SettingsUpdate") } + }; private readonly Dictionary session = new Dictionary(); private readonly Dictionary settings; @@ -25,20 +34,39 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin { } } - public Boolean ParseReuqest(HttpListenerContext cont) => - cont.Request.Url.PathAndQuery == "/admin/login" ? this.Login(cont) : - !this.CheckAuth(cont) ? false : - cont.Request.Url.PathAndQuery.StartsWith("/admin/get_json_") ? this.GetJsonFiles(cont) : - cont.Request.Url.PathAndQuery.StartsWith("/admin/set_json_") ? this.SetJsonFiles(cont) : - Webserver.SendFileResponse(cont); + public Boolean ParseReuqest(HttpListenerContext cont) { + if(cont.Request.Url.PathAndQuery == "/admin/login") { + return this.Login(cont); + } + if(!this.CheckAuth(cont)) { + return false; + } + if(cont.Request.Url.PathAndQuery.StartsWith("/admin/api/json/")) { + if(cont.Request.HttpMethod == "GET") { + if(cont.Request.Url.AbsolutePath.Length > 16) { + String parts = cont.Request.Url.AbsolutePath[16..]; + Dictionary ret = new Dictionary(); + foreach(String part in parts.Split(",")) { + if(this.datastorage.ContainsKey(part)) { + ret.Add(part, JsonMapper.ToObject(File.ReadAllText("json/" + this.datastorage[part].Item1 + ".json"))); + } + } + Console.WriteLine("200 - Send names.json " + cont.Request.Url.PathAndQuery); + return Webserver.SendJsonResponse(ret, cont); + } + } 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 Webserver.SendFileResponse(cont); + } - private Boolean SetJsonFiles(HttpListenerContext cont) => - cont.Request.Url.PathAndQuery == "/admin/set_json_names" ? this.SetJsonFile(cont, "names.json", this.NamesUpdate) : - cont.Request.Url.PathAndQuery == "/admin/set_json_geo" ? this.SetJsonFile(cont, "geo.json", this.GeoUpdate) : - cont.Request.Url.PathAndQuery == "/admin/set_json_settings" ? this.SetJsonFile(cont, "settings.json", this.SettingsUpdate) : - false; - - private Boolean SetJsonFile(HttpListenerContext cont, String filename, AdminEvent updatenotifier) { + private Boolean SetJsonFile(HttpListenerContext cont, String filename, String updatenotifier) { StreamReader reader = new StreamReader(cont.Request.InputStream, cont.Request.ContentEncoding); String rawData = reader.ReadToEnd(); cont.Request.InputStream.Close(); @@ -50,24 +78,9 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin { cont.Response.StatusCode = 501; return false; } - File.WriteAllText("json/"+ filename, rawData); - Console.WriteLine("200 - Post " + filename + " " + cont.Request.Url.PathAndQuery); - updatenotifier?.Invoke(this, new EventArgs()); - return true; - } - - private Boolean GetJsonFiles(HttpListenerContext cont) => - cont.Request.Url.PathAndQuery == "/admin/get_json_names" ? this.GetJsonFile(cont, "names.json") : - cont.Request.Url.PathAndQuery == "/admin/get_json_geo" ? this.GetJsonFile(cont, "geo.json") : - cont.Request.Url.PathAndQuery == "/admin/get_json_settings" ? this.GetJsonFile(cont, "settings.json") : - false; - - private Boolean GetJsonFile(HttpListenerContext cont, String filename) { - String file = File.ReadAllText("json/" + filename); - Byte[] buf = Encoding.UTF8.GetBytes(file); - cont.Response.ContentLength64 = buf.Length; - cont.Response.OutputStream.Write(buf, 0, buf.Length); - Console.WriteLine("200 - Send names.json " + cont.Request.Url.PathAndQuery); + File.WriteAllText(filename, rawData); + Console.WriteLine("200 - PUT " + filename + " " + cont.Request.Url.PathAndQuery); + this.GetEvent(updatenotifier)?.Invoke(this, new EventArgs()); return true; } diff --git a/Lora-Map/Model/Admin/AdminSession.cs b/Lora-Map/Model/Admin/AdminSession.cs index 42c7993..8444547 100644 --- a/Lora-Map/Model/Admin/AdminSession.cs +++ b/Lora-Map/Model/Admin/AdminSession.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin { class AdminSession { diff --git a/Lora-Map/Model/Camera.cs b/Lora-Map/Model/Camera/CameraCounter.cs similarity index 88% rename from Lora-Map/Model/Camera.cs rename to Lora-Map/Model/Camera/CameraCounter.cs index 48068c2..08fe7cc 100644 --- a/Lora-Map/Model/Camera.cs +++ b/Lora-Map/Model/Camera/CameraCounter.cs @@ -2,17 +2,15 @@ using System; using System.Globalization; -namespace Fraunhofer.Fit.IoT.LoraMap.Model -{ - class Camera - { +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Camera { + public class CameraCounter { public DateTime Lastcameradata { get; private set; } public String Name { get; private set; } public Int32 Total { get; private set; } public Int32 Incoming { get; private set; } public Int32 Outgoing { get; private set; } - public Camera(JsonData json) => this.Update(json); + public CameraCounter(JsonData json) => this.Update(json); internal static String GetId(JsonData json) => (String)json["camera_id"]; diff --git a/Lora-Map/Model/Crowd.cs b/Lora-Map/Model/Camera/CameraDensity.cs similarity index 92% rename from Lora-Map/Model/Crowd.cs rename to Lora-Map/Model/Camera/CameraDensity.cs index 2d22ed6..57b23c5 100644 --- a/Lora-Map/Model/Crowd.cs +++ b/Lora-Map/Model/Camera/CameraDensity.cs @@ -2,17 +2,15 @@ using System; using System.Globalization; -namespace Fraunhofer.Fit.IoT.LoraMap.Model -{ - public class Crowd - { +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Camera { + public class CameraDensity { public Int32 DensityCount { get; private set; } public DateTime TimeStamp { get; private set; } public Double AverageFlowMagnitude { get; private set; } public Double AverageFlowDirection { get; private set; } public DateTime LastUpdate { get; private set; } - public Crowd(JsonData json) => this.Update(json); + public CameraDensity(JsonData json) => this.Update(json); public static Boolean CheckJsonCrowdDensityLocal(JsonData json) => json.ContainsKey("camera_ids") && json["camera_ids"].IsArray && json["camera_ids"].Count == 1 && json.ContainsKey("density_map") && json["density_map"].IsArray && diff --git a/Lora-Map/Model/Fight.cs b/Lora-Map/Model/Camera/CameraFights.cs similarity index 89% rename from Lora-Map/Model/Fight.cs rename to Lora-Map/Model/Camera/CameraFights.cs index d937cdb..32a259b 100644 --- a/Lora-Map/Model/Fight.cs +++ b/Lora-Map/Model/Camera/CameraFights.cs @@ -2,9 +2,9 @@ using System; using System.Globalization; -namespace Fraunhofer.Fit.IoT.LoraMap.Model { - public class Fight { - public Fight(JsonData json) => this.Update(json); +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Camera { + public class CameraFights { + public CameraFights(JsonData json) => this.Update(json); public DateTime LastUpdate { get; private set; } public DateTime TimeStamp { get; private set; } diff --git a/Lora-Map/Model/Camera/CameraModel.cs b/Lora-Map/Model/Camera/CameraModel.cs new file mode 100644 index 0000000..084697a --- /dev/null +++ b/Lora-Map/Model/Camera/CameraModel.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using BlubbFish.Utils; + +using LitJson; + +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Camera { + public class CameraModel : OwnSingeton { + private readonly Object lockFight = new Object(); + private readonly Object lockCount = new Object(); + private readonly Object lockDensy = new Object(); + + public SortedDictionary Counter { + get; private set; + } + public SortedDictionary Density { + get; private set; + } + public SortedDictionary Fights { + get; private set; + } + + protected CameraModel() { + this.Counter = new SortedDictionary(); + this.Density = new SortedDictionary(); + this.Fights = new SortedDictionary(); + } + + public void ParseMqttJson(JsonData mqtt, String from) { + if(from.Contains("camera/count") && CameraCounter.CheckJson(mqtt)) { + String cameraid = CameraCounter.GetId(mqtt); + lock(this.lockCount) { + if(this.Counter.ContainsKey(cameraid)) { + this.Counter[cameraid].Update(mqtt); + } else { + this.Counter.Add(cameraid, new CameraCounter(mqtt)); + } + } + } else if((from.Contains("sfn/crowd_density_local") || from.Contains("camera/crowd")) && CameraDensity.CheckJsonCrowdDensityLocal(mqtt) || from.Contains("sfn/flow") && CameraDensity.CheckJsonFlow(mqtt)) { + String cameraid = CameraDensity.GetId(mqtt); + lock(this.lockDensy) { + if(this.Density.ContainsKey(cameraid)) { + this.Density[cameraid].Update(mqtt); + } else { + this.Density.Add(cameraid, new CameraDensity(mqtt)); + } + } + } else if((from.Contains("camera/fighting_detection") || from.Contains("sfn/fighting_detection")) && CameraFights.CheckJsonFightingDetection(mqtt)) { + String cameraid = CameraFights.GetId(mqtt); + lock(this.lockFight) { + if(this.Fights.ContainsKey(cameraid)) { + this.Fights[cameraid].Update(mqtt); + } else { + this.Fights.Add(cameraid, new CameraFights(mqtt)); + } + } + } + } + } +} diff --git a/Lora-Map/Model/Marker.cs b/Lora-Map/Model/Marker.cs deleted file mode 100644 index e6b1510..0000000 --- a/Lora-Map/Model/Marker.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System; -using System.IO; -using System.Xml; -using LitJson; - -namespace Fraunhofer.Fit.IoT.LoraMap.Model -{ - class Marker { - private readonly XmlDocument svg = new XmlDocument(); - - public Marker(String hash) { - this.svg.LoadXml(File.ReadAllText("resources/icons/marker/Marker.svg")); - this.ParseParams(hash); - } - - public static String ParseMarkerConfig(JsonData json, String name) { - String ret = "icons/marker/Marker.svg"; - if(json.ContainsKey("person") && json["person"].IsObject) { - ret += "?icon=person"; - if(json["person"].ContainsKey("org") && json["person"]["org"].IsString) { - ret += "&person-org=" + (String)json["person"]["org"]; - } - if(json["person"].ContainsKey("funct") && json["person"]["funct"].IsString) { - ret += "&person-funct=" + (String)json["person"]["funct"]; - } - if(json["person"].ContainsKey("rang") && json["person"]["rang"].IsString) { - ret += "&person-rang=" + (String)json["person"]["rang"]; - } - if(json["person"].ContainsKey("text") && json["person"]["text"].IsString) { - ret += "&person-text=" + (String)json["person"]["text"]; - } - if(json["person"].ContainsKey("typ") && json["person"]["typ"].IsArray) { - foreach(JsonData item in json["person"]["typ"]) { - if(item.IsString) { - ret += "&person-typ=" + (String)item; - } - } - } - } - ret += ret.Contains("?") ? "&name=" + name : "?name=" + name; - return ret; - } - - private void ParseParams(String hash) { - String[] parts = hash.Split('&'); - foreach(String part in parts) { - String[] keyvalue = part.Split('='); - if(keyvalue.Length == 2) { - switch(keyvalue[0].ToLower()) { - case "name": - XmlNodeList xmlname = this.svg.DocumentElement.SelectNodes("//*[local-name()='tspan'][@id='marker-name-text']"); - if(xmlname.Count == 1) { - xmlname.Item(0).InnerText = keyvalue[1]; - } - break; - case "marker-bg": - if(keyvalue[1].ToLower() == "hidden") { - XmlNodeList markerbg = this.svg.DocumentElement.SelectNodes("//*[local-name()='defs'][@id='global-def']"); - if(markerbg.Count == 1) { - markerbg[0].InnerXml += ""; - } - XmlNodeList root = this.svg.DocumentElement.SelectNodes("//*[local-name()='svg']"); - if(root.Count == 1) { - foreach(XmlAttribute item in root[0].Attributes) { - if(item.Name.ToLower() == "height") { - item.Value = "38px"; - } - if(item.Name.ToLower() == "width") { - item.Value = "40px"; - } - if(item.Name.ToLower() == "viewbox") { - item.Value = "8 35 70 100"; - } - } - } - } - break; - case "icon": - if(keyvalue[1].ToLower() == "person") { - XmlNodeList xmlicon = this.svg.DocumentElement.SelectNodes("//*[local-name()='defs'][@id='global-def']"); - if (xmlicon.Count == 1) { - xmlicon.Item(0).InnerXml += ""; - } - } - break; - case "person-org": - XmlNodeList xmlpersonorg = this.svg.DocumentElement.SelectNodes("//*[local-name()='defs'][@id='people-def']"); - if (xmlpersonorg.Count == 1) { - xmlpersonorg.Item(0).InnerXml += ""; - } - break; - case "person-funct": - XmlNodeList xmlpersonfunct = this.svg.DocumentElement.SelectNodes("//*[local-name()='defs'][@id='people-def']"); - if (xmlpersonfunct.Count == 1) { - xmlpersonfunct.Item(0).InnerXml += ""; - } - break; - case "person-rang": - XmlNodeList xmlpersonrang = this.svg.DocumentElement.SelectNodes("//*[local-name()='defs'][@id='people-def']"); - if (xmlpersonrang.Count == 1) { - xmlpersonrang.Item(0).InnerXml += ""; - } - break; - case "person-text": - XmlNodeList xmlpersontext = this.svg.DocumentElement.SelectNodes("//*[local-name()='tspan'][@id='person-layer-typ-text']"); - if (xmlpersontext.Count == 1) { - xmlpersontext.Item(0).InnerText = keyvalue[1]; - } - break; - case "person-typ": - XmlNodeList xmlpersontyp = this.svg.DocumentElement.SelectNodes("//*[local-name()='defs'][@id='people-def']"); - if(xmlpersontyp.Count == 1) { - xmlpersontyp.Item(0).InnerXml += ""; - } - break; - } - } - } - } - - public override String ToString() => this.svg.OuterXml; - } -} diff --git a/Lora-Map/Model/AlarmItem.cs b/Lora-Map/Model/Position/PositionAlarm.cs similarity index 81% rename from Lora-Map/Model/AlarmItem.cs rename to Lora-Map/Model/Position/PositionAlarm.cs index 83c02fa..c5b8db4 100644 --- a/Lora-Map/Model/AlarmItem.cs +++ b/Lora-Map/Model/Position/PositionAlarm.cs @@ -3,13 +3,13 @@ using System.Collections.Generic; using System.Linq; using LitJson; -namespace Fraunhofer.Fit.IoT.LoraMap.Model { - public class AlarmItem : PositionItem { +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position { + public class PositionAlarm : PositionItem { private readonly SortedDictionary buttonhistory = new SortedDictionary(); public List ButtonPressed => this.buttonhistory.Keys.ToList(); - public AlarmItem(JsonData json) : base(json, null) { + public PositionAlarm(JsonData json) : base(json, null) { } public override void Update(JsonData json) { diff --git a/Lora-Map/Model/PositionItem.cs b/Lora-Map/Model/Position/PositionItem.cs similarity index 80% rename from Lora-Map/Model/PositionItem.cs rename to Lora-Map/Model/Position/PositionItem.cs index db742f0..0c45c72 100644 --- a/Lora-Map/Model/PositionItem.cs +++ b/Lora-Map/Model/Position/PositionItem.cs @@ -1,8 +1,11 @@ using System; using System.Globalization; + +using Fraunhofer.Fit.IoT.LoraMap.Model.Svg; + using LitJson; -namespace Fraunhofer.Fit.IoT.LoraMap.Model { +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position { public class PositionItem { private Double _lastLat = 0; private Double _lastLon = 0; @@ -22,6 +25,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { public Double Height { get; private set; } public String Name { get; private set; } public String Icon { get; private set; } + public String MenuIcon { get; private set; } public String Group { get; private set; } public PositionItem(JsonData json, JsonData marker) { @@ -32,7 +36,9 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { 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; - this.Icon = marker[id].ContainsKey("marker.svg") && marker[id]["marker.svg"].IsObject ? Marker.ParseMarkerConfig(marker[id]["marker.svg"], this.Name) : marker[id].ContainsKey("icon") && marker[id]["icon"].IsString ? (String)marker[id]["icon"] : null; + Tuple icons = this.ParseIconConfig(marker[id]); + this.Icon = icons.Item1; + this.MenuIcon = icons.Item2; this.Group = marker[id].ContainsKey("Group") && marker[id]["Group"].IsString ? (String)marker[id]["Group"] : "no"; } else { this.Name = id; @@ -40,6 +46,21 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { this.Group = null; } } + + private Tuple ParseIconConfig(JsonData 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"]); + } + } else if(marker.ContainsKey("icon") && marker["icon"].IsString) { + icon = (String)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 diff --git a/Lora-Map/Model/Position/PositionModel.cs b/Lora-Map/Model/Position/PositionModel.cs new file mode 100644 index 0000000..35ffc85 --- /dev/null +++ b/Lora-Map/Model/Position/PositionModel.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.IO; + +using BlubbFish.Utils; + +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; + + public SortedDictionary Positions { + get; private set; + } + + public SortedDictionary Alarms { + get; private set; + } + + protected PositionModel() { + this.Positions = new SortedDictionary(); + this.Alarms = new SortedDictionary(); + this.CheckJsonFile(); + this.marker = JsonMapper.ToObject(File.ReadAllText("json/names.json")); + + } + + public void ParseMqttJson(JsonData mqtt, String from) { + if((from.Contains("lora/data") || from.Contains("lora/panic")) && PositionItem.CheckJson(mqtt)) { + String name = PositionItem.GetId(mqtt); + lock(this.lockData) { + if(this.Positions.ContainsKey(name)) { + this.Positions[name].Update(mqtt); + } else { + this.Positions.Add(name, new PositionItem(mqtt, this.marker)); + } + } + if(from.Contains("lora/panic")) { + lock(this.lockPanic) { + if(this.Alarms.ContainsKey(name)) { + this.Alarms[name].Update(mqtt); + } else { + this.Alarms.Add(name, new PositionAlarm(mqtt)); + } + } + Console.WriteLine("PANIC erhalten!"); + } + Console.WriteLine("Koordinate erhalten!"); + } + } + + public void ReloadNames(Object sender, EventArgs e) { + this.CheckJsonFile(); + this.marker = JsonMapper.ToObject(File.ReadAllText("json/names.json")); + 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/EnviromentData.cs b/Lora-Map/Model/Sensor/SensorEnviromentData.cs similarity index 90% rename from Lora-Map/Model/EnviromentData.cs rename to Lora-Map/Model/Sensor/SensorEnviromentData.cs index 920563f..938b9ca 100644 --- a/Lora-Map/Model/EnviromentData.cs +++ b/Lora-Map/Model/Sensor/SensorEnviromentData.cs @@ -3,8 +3,8 @@ using System.Globalization; using LitJson; -namespace Fraunhofer.Fit.IoT.LoraMap.Model { - class EnviromentData { +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Sensor { + public class SensorEnviromentData { public String Name { get; private set; } public Double Rssi { get; private set; } public Double Snr { get; private set; } @@ -13,7 +13,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { public Double Windspeed { get; private set; } public DateTime Lorarecievedtime { get; private set; } - public EnviromentData(JsonData json) => this.Update(json); + public SensorEnviromentData(JsonData json) => this.Update(json); public void Update(JsonData json) { this.Name = GetId(json); diff --git a/Lora-Map/Model/Sensor/SensorModel.cs b/Lora-Map/Model/Sensor/SensorModel.cs new file mode 100644 index 0000000..19c115b --- /dev/null +++ b/Lora-Map/Model/Sensor/SensorModel.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using BlubbFish.Utils; + +using LitJson; + +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Sensor { + public class SensorModel : OwnSingeton { + private readonly Object lockSensor = new Object(); + + public SortedDictionary Enviroments { + get; private set; + } + public SensorWeather Weather { + get; private set; + } + + protected SensorModel() { + this.Enviroments = new SortedDictionary(); + this.Weather = new SensorWeather(); + } + + public void ParseMqttJson(JsonData mqtt, String from) { + if(from.Contains("lora/sensor") && SensorEnviromentData.CheckJson(mqtt)) { + String sensorid = SensorEnviromentData.GetId(mqtt); + lock(this.lockSensor) { + if(this.Enviroments.ContainsKey(sensorid)) { + this.Enviroments[sensorid].Update(mqtt); + } else { + this.Enviroments.Add(sensorid, new SensorEnviromentData(mqtt)); + } + } + Console.WriteLine("Umweltdaten erhalten!"); + } + } + + public void Dispose() => this.Weather.Dispose(); + } +} diff --git a/Lora-Map/Model/WeatherWarnings.cs b/Lora-Map/Model/Sensor/SensorWeather.cs similarity index 91% rename from Lora-Map/Model/WeatherWarnings.cs rename to Lora-Map/Model/Sensor/SensorWeather.cs index 39d6214..8e27e59 100644 --- a/Lora-Map/Model/WeatherWarnings.cs +++ b/Lora-Map/Model/Sensor/SensorWeather.cs @@ -6,21 +6,18 @@ using Fraunhofer.Fit.IoT.LoraMap.Lib; using LitJson; -namespace Fraunhofer.Fit.IoT.LoraMap.Model { - public class WeatherWarnings { - private readonly Settings settings; +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Sensor { + public class SensorWeather { private Thread bgthread; private Boolean backgroundrunnerAlive; private readonly WebRequests webrequests = new WebRequests(); public List Warnungen { get; private set; } - public WeatherWarnings(Settings settings) { - this.settings = settings; - this.StartBackgroundThread(); - } + public SensorWeather() => this.StartBackgroundThread(); private void StartBackgroundThread() { + this.Warnungen = new List(); this.bgthread = new Thread(this.BackGroundRunner); this.backgroundrunnerAlive = true; this.bgthread.Start(); @@ -29,7 +26,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { private void BackGroundRunner() { while(this.backgroundrunnerAlive) { List ret = new List(); - foreach(Int32 item in this.settings.GetWeatherCellIds()) { + foreach(Int32 item in Settings.Instance.Internal.WeatherCellIDs) { try { JsonData json = this.webrequests.GetJson("https://maps.dwd.de/geoserver/wfs?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&typeName=dwd:Warnungen_Gemeinden&outputFormat=application/json&cql_filter=WARNCELLID=" + item); if (json.ContainsKey("features") && json["features"].IsArray && json["features"].Count > 0) { @@ -50,10 +47,10 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { } } - internal void Dispose() { + public void Dispose() { try { this.backgroundrunnerAlive = false; - while (this.bgthread.IsAlive) { + while (this.bgthread != null && this.bgthread.IsAlive) { Thread.Sleep(10); } this.bgthread = null; diff --git a/Lora-Map/Model/Settings.cs b/Lora-Map/Model/Settings.cs index b2b7001..bf4d88d 100644 --- a/Lora-Map/Model/Settings.cs +++ b/Lora-Map/Model/Settings.cs @@ -1,78 +1,88 @@ -using CoordinateSharp; +using BlubbFish.Utils; + +using CoordinateSharp; using LitJson; using System; using System.Collections.Generic; using System.IO; namespace Fraunhofer.Fit.IoT.LoraMap.Model { - public class Settings { - private readonly List weatherCellIDs = new List(); + public class Settings : OwnSingeton { + private Int32 gridradius; - public Double Startloclat { get; private set; } - public Double Startloclon { get; private set; } - public Dictionary>>> Grid { get; private set; } - public Dictionary FightDedection { get; private set; } - public Dictionary DensityArea { get; private set; } - public Dictionary Sensors { get; private set; } + public PublicSettings External { + get; set; + } - public Settings() => this.ParseJson(); - - public void AdminModelUpdateSettings(Object sender, EventArgs e) => this.ParseJson(); + public PrivateSettings Internal { + get; set; + } - private void ParseJson() { + protected Settings() { + this.External = new PublicSettings(); + this.Internal = new PrivateSettings(); + this.ParseSettingsJson(); + this.ParseGeoJson(); + } + + public void ReloadSettings(Object sender, EventArgs e) => this.ParseSettingsJson(); + public void ReloadGeo(Object sender, EventArgs e) => this.ParseGeoJson(); + + private void ParseSettingsJson() { + this.CheckJsonFiles(); JsonData json = JsonMapper.ToObject(File.ReadAllText("json/settings.json")); - if(json.ContainsKey("StartPos") && json["StartPos"].IsObject && json["StartPos"].ContainsKey("lat") && json["StartPos"]["lat"].IsDouble && json["StartPos"].ContainsKey("lon") && json["StartPos"]["lon"].IsDouble) { - this.Startloclat = (Double)json["StartPos"]["lat"]; - this.Startloclon = (Double)json["StartPos"]["lon"]; + if(json.ContainsKey("StartPos") && json["StartPos"].IsObject && json["StartPos"].ContainsKey("lat") && (json["StartPos"]["lat"].IsDouble || json["StartPos"]["lat"].IsInt) && json["StartPos"].ContainsKey("lon") && (json["StartPos"]["lon"].IsDouble || json["StartPos"]["lon"].IsInt)) { + this.External.Startloclat = Double.Parse(json["StartPos"]["lat"].ToString()); + this.External.Startloclon = Double.Parse(json["StartPos"]["lon"].ToString()); } else { - this.Startloclat = 0; - this.Startloclon = 0; + this.External.Startloclat = 0; + this.External.Startloclon = 0; } - this.weatherCellIDs.Clear(); + this.Internal.WeatherCellIDs.Clear(); if(json.ContainsKey("CellIds") && json["CellIds"].IsArray && json["CellIds"].Count > 0) { - foreach (JsonData item in json["CellIds"]) { + foreach(JsonData item in json["CellIds"]) { if(Int32.TryParse(item.ToString(), out Int32 cellid)) { - this.weatherCellIDs.Add(cellid); + this.Internal.WeatherCellIDs.Add(cellid); } } } if(json.ContainsKey("FightDedection") && json["FightDedection"].IsObject) { Dictionary fights = new Dictionary(); - foreach (KeyValuePair entry in json["FightDedection"]) { + foreach(KeyValuePair entry in json["FightDedection"]) { Fight fight = new Fight { Polygon = new List>() }; if(entry.Value.ContainsKey("Poly") && entry.Value["Poly"].IsArray) { - foreach (JsonData coord in entry.Value["Poly"]) { + foreach(JsonData coord in entry.Value["Poly"]) { List coords = new List(); - if (coord.ContainsKey("Lat") && coord["Lat"].IsDouble && coord.ContainsKey("Lon") && coord["Lon"].IsDouble) { + if(coord.ContainsKey("Lat") && coord["Lat"].IsDouble && coord.ContainsKey("Lon") && coord["Lon"].IsDouble) { coords.Add((Double)coord["Lat"]); coords.Add((Double)coord["Lon"]); } fight.Polygon.Add(coords); } } - if (entry.Value.ContainsKey("Level") && entry.Value["Level"].IsDouble) { + if(entry.Value.ContainsKey("Level") && entry.Value["Level"].IsDouble) { fight.Level = (Double)entry.Value["Level"]; } - if (entry.Value.ContainsKey("Alias") && entry.Value["Alias"].IsString) { + if(entry.Value.ContainsKey("Alias") && entry.Value["Alias"].IsString) { fight.Alias = (String)entry.Value["Alias"]; } fights.Add(entry.Key, fight); } - this.FightDedection = fights; + this.External.FightDedection = fights; } if(json.ContainsKey("CrwodDensity") && json["CrwodDensity"].IsObject) { Dictionary densitys = new Dictionary(); - foreach (KeyValuePair entry in json["CrwodDensity"]) { + foreach(KeyValuePair entry in json["CrwodDensity"]) { Density density = new Density { Polygon = new List>() }; - if (entry.Value.ContainsKey("Poly") && entry.Value["Poly"].IsArray) { - foreach (JsonData coord in entry.Value["Poly"]) { + if(entry.Value.ContainsKey("Poly") && entry.Value["Poly"].IsArray) { + foreach(JsonData coord in entry.Value["Poly"]) { List coords = new List(); - if (coord.ContainsKey("Lat") && coord["Lat"].IsDouble && coord.ContainsKey("Lon") && coord["Lon"].IsDouble) { + if(coord.ContainsKey("Lat") && coord["Lat"].IsDouble && coord.ContainsKey("Lon") && coord["Lon"].IsDouble) { coords.Add((Double)coord["Lat"]); coords.Add((Double)coord["Lon"]); } @@ -87,7 +97,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { } densitys.Add(entry.Key, density); } - this.DensityArea = densitys; + this.External.DensityArea = densitys; } if(json.ContainsKey("Sensors") && json["Sensors"].IsObject) { Dictionary sensors = new Dictionary(); @@ -112,31 +122,37 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { sensors.Add(entry.Key, sensor); } } - this.Sensors = sensors; + this.External.Sensors = sensors; } - this.gridradius = json.ContainsKey("GridRadius") && json["GridRadius"].IsInt && this.Startloclat != 0 && this.Startloclon != 0 ? (Int32)json["GridRadius"] : 0; + this.gridradius = json.ContainsKey("GridRadius") && json["GridRadius"].IsInt && this.External.Startloclat != 0 && this.External.Startloclon != 0 ? (Int32)json["GridRadius"] : 0; this.GenerateGrid(); + this.FindMapLayer(); + } + + private void ParseGeoJson() { + this.CheckJsonFiles(); + this.External.GeoLayer = JsonMapper.ToObject(File.ReadAllText("json/geo.json")); } private void GenerateGrid() { - this.Grid = new Dictionary>>> { + this.External.Grid = new Dictionary>>> { { "Major", new List>>() }, { "Minor", new List>>() } }; - if (this.Startloclat == 0 || this.Startloclon == 0 || this.gridradius == 0) { + if(this.External.Startloclat == 0 || this.External.Startloclon == 0 || this.gridradius == 0) { return; } - MilitaryGridReferenceSystem start = new Coordinate(this.Startloclat, this.Startloclon).MGRS; + MilitaryGridReferenceSystem start = new Coordinate(this.External.Startloclat, this.External.Startloclon).MGRS; Double left = start.Easting - this.gridradius - (start.Easting - this.gridradius) % 100; Double bottom = start.Northing - this.gridradius - (start.Northing - this.gridradius) % 100; Double right = start.Easting + this.gridradius + (100 - (start.Easting + this.gridradius) % 100); Double top = start.Northing + this.gridradius + (100 - (start.Northing + this.gridradius) % 100); - for (Double i = left; i <= right; i += 50) { + for(Double i = left; i <= right; i += 50) { Coordinate TopLeft = MilitaryGridReferenceSystem.MGRStoLatLong(new MilitaryGridReferenceSystem(start.LatZone, start.LongZone, start.Digraph, i, top)); Coordinate BottomLeft = MilitaryGridReferenceSystem.MGRStoLatLong(new MilitaryGridReferenceSystem(start.LatZone, start.LongZone, start.Digraph, i, bottom)); - if(i%100 == 0) { - this.Grid["Major"].Add(new Dictionary> { + if(i % 100 == 0) { + this.External.Grid["Major"].Add(new Dictionary> { { "from", new List { TopLeft.Latitude.DecimalDegree, TopLeft.Longitude.DecimalDegree @@ -149,7 +165,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { } }); } else { - this.Grid["Minor"].Add(new Dictionary> { + this.External.Grid["Minor"].Add(new Dictionary> { { "from", new List { TopLeft.Latitude.DecimalDegree, TopLeft.Longitude.DecimalDegree @@ -163,11 +179,11 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { }); } } - for (Double i = bottom; i <= top; i += 50) { + for(Double i = bottom; i <= top; i += 50) { Coordinate BottomLeft = MilitaryGridReferenceSystem.MGRStoLatLong(new MilitaryGridReferenceSystem(start.LatZone, start.LongZone, start.Digraph, left, i)); Coordinate BottomRight = MilitaryGridReferenceSystem.MGRStoLatLong(new MilitaryGridReferenceSystem(start.LatZone, start.LongZone, start.Digraph, right, i)); - if (i % 100 == 0) { - this.Grid["Major"].Add(new Dictionary> { + if(i % 100 == 0) { + this.External.Grid["Major"].Add(new Dictionary> { { "from", new List { BottomLeft.Latitude.DecimalDegree, BottomLeft.Longitude.DecimalDegree @@ -180,7 +196,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { } }); } else { - this.Grid["Minor"].Add(new Dictionary> { + this.External.Grid["Minor"].Add(new Dictionary> { { "from", new List { BottomLeft.Latitude.DecimalDegree, BottomLeft.Longitude.DecimalDegree @@ -196,24 +212,117 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { } } - public List GetWeatherCellIds() => this.weatherCellIDs; + private void FindMapLayer() { + this.External.Layers = new Dictionary> { + { "online", new Dictionary() { + { "title", "Online Map" }, + { "url", "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" }, + { "attribution", "© OpenStreetMap contributors" }, + { "minZoom", 1 }, + { "maxZoom", 19 } + } } + }; + if(Directory.Exists("resources" + Path.DirectorySeparatorChar + "maps")) { + String[] dirs = Directory.GetDirectories("resources" + Path.DirectorySeparatorChar + "maps"); + foreach(String dir in dirs) { + if(File.Exists(dir + Path.DirectorySeparatorChar + "tiles.json")) { + try { + JsonData map = JsonMapper.ToObject(File.ReadAllText(dir + Path.DirectorySeparatorChar + "tiles.json")); + Dictionary entry = new Dictionary { + { "title", (String)map["name"] }, + { "url", (String)map["tiles"][0] }, + { "attribution", (String)map["attribution"] }, + { "minZoom", (Int32)map["minzoom"] }, + { "maxZoom", (Int32)map["maxzoom"] }, + { "bounds", new Dictionary() { + { "corner1", new Double[] { (Double)map["bounds"][0], (Double)map["bounds"][1] } }, + { "corner2", new Double[] { (Double)map["bounds"][2], (Double)map["bounds"][3] } } + } } + }; + this.External.Layers.Add(dir[(("resources" + Path.DirectorySeparatorChar + "maps").Length + 1)..], entry); + } catch { } + } + } + } + } + + private void CheckJsonFiles() { + if(!Directory.Exists("json")) { + _ = Directory.CreateDirectory("json"); + } + if(!File.Exists("json/settings.json")) { + File.WriteAllText("json/settings.json", "{}"); + } + if(!File.Exists("json/geo.json")) { + File.WriteAllText("json/geo.json", "{}"); + } + } public struct Density { - public List> Polygon { get; set; } - public Int32 Maximum { get; set; } - public String Alias { get; set; } + public List> Polygon { + get; set; + } + public Int32 Maximum { + get; set; + } + public String Alias { + get; set; + } } public struct Fight { - public List> Polygon { get; set; } - public Double Level { get; set; } - public String Alias { get; set; } + public List> Polygon { + get; set; + } + public Double Level { + get; set; + } + public String Alias { + get; set; + } } public struct Sensor { - public List Coordinates { get; set; } - public Double Level { get; set; } - public String Alias { get; set; } + public List Coordinates { + get; set; + } + public Double Level { + get; set; + } + public String Alias { + get; set; + } + } + + public class PublicSettings { + public Double Startloclat { + get; set; + } = 0; + public Double Startloclon { + get; set; + } = 0; + public Dictionary>>> Grid { + get; set; + } = new Dictionary>>>(); + public Dictionary FightDedection { + get; set; + } = new Dictionary(); + public Dictionary DensityArea { + get; set; + } = new Dictionary(); + public Dictionary Sensors { + get; set; + } = new Dictionary(); + public Dictionary> Layers { + get; set; + } = new Dictionary>(); + public JsonData GeoLayer { + get; set; + } + } + + public class PrivateSettings { + public List WeatherCellIDs { get; set; } = new List(); } } } diff --git a/Lora-Map/Model/Svg/SVGFile.cs b/Lora-Map/Model/Svg/SVGFile.cs new file mode 100644 index 0000000..714011c --- /dev/null +++ b/Lora-Map/Model/Svg/SVGFile.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Web; + +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { + public abstract class SVGFile { + protected String query; + protected Double width; + protected Double height; + protected List viewbox; + private readonly Boolean withSvgHeader; + protected List css = new List(); + + public SVGFile(String query, Double width, Double heigt, List viewbox, Boolean withSvGHeader = true) { + this.query = query; + this.width = width; + this.height = heigt; + this.viewbox = viewbox; + this.withSvgHeader = withSvGHeader; + this.ParseParams(); + #region add css font + if(withSvGHeader) { + this.css.Add("@font-face {\nfont-family: DIN1451;\nsrc: url(data:application/font-woff;charset=utf-8;base64,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) format('woff');\n}"); + } + #endregion + } + + protected static String DictionaryConfigToString(Dictionary config) { + String query = ""; + if(config.Count > 0) { + query += "?"; + List queryparts = new List(); + foreach(KeyValuePair item in config) { + queryparts.Add(HttpUtility.UrlEncode(item.Key) + "=" + HttpUtility.UrlEncode(item.Value)); + } + query += String.Join("&", queryparts); + } + return query; + } + + protected abstract void ParseParams(); + + protected abstract String DrawSvgContent(); + + public override String ToString() { + String svg = ""; + if(this.withSvgHeader) { + svg += "\n"; + svg += $"\n"; + } + if(this.css.Count > 0) { + svg += "\n"; + } + svg += this.DrawSvgContent(); + if(this.withSvgHeader) { + svg += "\n"; + } + return svg; + } + } +} \ No newline at end of file diff --git a/Lora-Map/Model/Svg/SVGMarker.cs b/Lora-Map/Model/Svg/SVGMarker.cs new file mode 100644 index 0000000..2125eda --- /dev/null +++ b/Lora-Map/Model/Svg/SVGMarker.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using LitJson; + +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { + public class SVGMarker : SVGFile { + private String name; + private String icon; + + 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)); + + protected override void ParseParams() { + String[] parts = this.query.Split('&'); + foreach(String part in parts) { + String[] keyvalue = part.Split('='); + if(keyvalue.Length == 2) { + switch(keyvalue[0].ToLower()) { + case "name": + this.name = keyvalue[1]; + break; + case "icon": + this.icon = keyvalue[1].ToLower(); + break; + } + } + } + } + + public static Dictionary GenerateConfig(JsonData json, String name) { + Dictionary config = new Dictionary(); + if(name != "") { + config.Add("name", name); + } + if(json.ContainsKey("person") && json["person"].IsObject) { + config.Add("icon", "person"); + Dictionary personconfig = SVGPerson.GenerateConfig(json["person"]); + personconfig.ToList().ForEach(x => config.Add(x.Key, x.Value)); + } + return config; + } + + protected override String DrawSvgContent() { + String svg = "\n"; + svg += "\n"; + svg += "\n"; + svg += "\n"; + svg += "\n"; + + svg += "\n"; + svg += $"{this.name}\n"; + svg += "\n"; + + if(this.icon == "person") { + svg += "\n"; + svg += new SVGPerson(this.query, false); + svg += "\n"; + } + return svg; + } + } +} diff --git a/Lora-Map/Model/Svg/SVGPerson.cs b/Lora-Map/Model/Svg/SVGPerson.cs new file mode 100644 index 0000000..f2a6dac --- /dev/null +++ b/Lora-Map/Model/Svg/SVGPerson.cs @@ -0,0 +1,198 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +using LitJson; + +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { + public class SVGPerson : SVGFile { + private String organisation; + private String function; + private String rang; + private String text; + private String[] typs; + + + + public SVGPerson(String query, Boolean withOutline = true) : base(query, 74.953316, 84.703323, new List() { -37.5, -12, 74.953316, 84.703323 }, withOutline) { + this.css.Add("#person-layer-org rect {\n stroke: black;\n stroke-width: 3px;\n}"); + this.css.Add("#person-layer-funct path {\n stroke: #000000;\n stroke-width: 3px;\n fill: #000000;\n}"); + this.css.Add("#person-layer-rang circle {\n fill: #000000;\n}"); + this.css.Add("#person-layer-typ tspan {\n font-size: 20px;\n font-family: DIN1451;\n text-align: center;\n text-anchor: middle;\n fill: #000000;\n}"); + 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)); + + protected override void ParseParams() { + String[] parts = this.query.Split('&'); + foreach(String part in parts) { + String[] keyvalue = part.Split('='); + if(keyvalue.Length == 2) { + switch(keyvalue[0].ToLower()) { + case "person-org": + this.organisation = keyvalue[1].ToLower(); + break; + case "person-funct": + this.function = keyvalue[1].ToLower(); + break; + case "person-rang": + this.rang = keyvalue[1].ToLower(); + break; + case "person-text": + this.text = keyvalue[1]; + break; + case "person-typ": + this.typs = keyvalue[1].ToLower().Split(","); + 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()); + } + 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)); + } + return config; + } + + protected override String DrawSvgContent() { + String svg = ""; + if(this.organisation != null && this.orglookup.ContainsKey(this.organisation)) { + svg += "\n"; + svg += $"\n"; + svg += $"\n"; + svg += "\n"; + svg += "\n"; + } + if(this.function != null && this.funclookup.ContainsKey(this.function)) { + svg += "\n"; + svg += $"\n"; + svg += $"\n"; + svg += "\n"; + svg += "\n"; + } + if(this.rang != null && this.ranglookup.ContainsKey(this.rang)) { + svg += "\n"; + svg += $"\n"; + svg += "\n"; + foreach(Double item in this.ranglookup[this.rang].Circles) { + svg += $"\n"; + } + svg += "\n"; + svg += "\n"; + svg += "\n"; + } + if(this.text != null || this.typs != null && 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))) { + foreach(String typ in this.typs) { + svg += $"\n"; + foreach(Tuple item in this.typlookup[typ].Lines) { + svg += $"\n"; + } + svg += "\n"; + } + } + svg += "\n"; + } + return svg; + } + + private readonly Dictionary orglookup = new Dictionary() { + { "thw", new Organistaion("THW", "#0069b4") }, + { "fw", new Organistaion("Feuerwehr", "#e30613") }, + { "hilo", new Organistaion("Hilo", "#ffffff") }, + { "pol", new Organistaion("Polizei", "#13a538") }, + { "fueh", new Organistaion("Führung", "#ffed00") }, + { "sonst", new Organistaion("Sonstig", "#ec6725") } + }; + private readonly Dictionary funclookup = new Dictionary() { + { "sonder", new Funktion("Sonder", "M -10,10 H 10") }, + { "fueh", new Funktion("Führungskraft", "M -10,10 H 10 L 0,0 Z") } + }; + private readonly Dictionary ranglookup = new Dictionary() { + { "trupp", new Rang("Truppführer", new List() { 0 }) }, + { "grupp", new Rang("Gruppenführer", new List() { -4.5, 4.5 }) }, + { "zug", new Rang("Zugführer", new List() { -9, 0, 9 }) } + }; + private readonly Dictionary typlookup = new Dictionary() { + { "loesch", new Typ("Brandbekämpfung/Löscheinsatz", new List>() { new Tuple(-35, 35.5, 35, 35.5), new Tuple(17.5, 35.5, 25, 26), new Tuple(17.5, 35.5, 25, 44) }) }, + { "sani", new Typ("Rettungswesen, Sanitätswesen, Gesundheitswesen", new List>() { new Tuple(0, 0, 0, 70), new Tuple(-35, 35.5, 35, 35.5) }) }, + { "betreu", new Typ("Betreuung", new List>() { new Tuple(-17, 53, 0, 35.5), new Tuple(17, 53, 0, 35.5) }) } + }; + + private struct Organistaion { + public String Name { + get; + } + public String Color { + get; + } + public Organistaion(String name, String color) { + this.Name = name; + this.Color = color; + } + } + private struct Funktion { + public String Name { + get; + } + public String Path { + get; + } + public Funktion(String name, String path) { + this.Name = name; + this.Path = path; + } + } + private struct Rang { + public String Name { + get; + } + public List Circles { + get; + } + public Rang(String name, List circles) { + this.Name = name; + this.Circles = circles; + } + } + private struct Typ { + public String Name { + get; + } + public List> Lines { + get; + } + public Typ(String name, List> lines) { + this.Name = name; + this.Lines = lines; + } + } + } +} \ No newline at end of file diff --git a/Lora-Map/Model/Svg/SvgModel.cs b/Lora-Map/Model/Svg/SvgModel.cs new file mode 100644 index 0000000..12d9f2d --- /dev/null +++ b/Lora-Map/Model/Svg/SvgModel.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Text; + +using BlubbFish.Utils; + +namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg { + public class SvgModel : OwnSingeton { + private readonly Dictionary svgtable = new Dictionary(); + public Boolean ParseRequest(HttpListenerContext cont) { + Byte[] svg = this.GetSvg(cont.Request.Url.PathAndQuery); + if(svg.Length > 0) { + cont.Response.ContentType = "image/svg+xml"; + cont.Response.ContentLength64 = svg.Length; + cont.Response.OutputStream.Write(svg, 0, svg.Length); + Console.WriteLine("200 - " + cont.Request.Url.PathAndQuery); + return true; + } + cont.Response.StatusCode = 404; + Helper.WriteError("404 - " + cont.Request.Url.PathAndQuery + " not found!"); + return false; + } + + private Byte[] GetSvg(String pathAndQuery) { + if(this.svgtable.ContainsKey(pathAndQuery)) { + return Encoding.UTF8.GetBytes(this.svgtable[pathAndQuery].ToString()); + } else { + if(pathAndQuery.StartsWith("/api/svg/marker.svg") && pathAndQuery.Contains("?")) { + String query = pathAndQuery[(pathAndQuery.IndexOf('?') + 1)..]; + this.svgtable.Add(pathAndQuery, new SVGMarker(query)); + return Encoding.UTF8.GetBytes(this.svgtable[pathAndQuery].ToString()); + } else if(pathAndQuery.StartsWith("/api/svg/person.svg") && pathAndQuery.Contains("?")) { + String query = pathAndQuery[(pathAndQuery.IndexOf('?') + 1)..]; + this.svgtable.Add(pathAndQuery, new SVGPerson(query)); + return Encoding.UTF8.GetBytes(this.svgtable[pathAndQuery].ToString()); + } + } + return new Byte[0]; + } + } +} diff --git a/Lora-Map/Server.cs b/Lora-Map/Server.cs index 9c33f5a..81721fb 100644 --- a/Lora-Map/Server.cs +++ b/Lora-Map/Server.cs @@ -1,141 +1,48 @@ using System; using System.Collections.Generic; -using System.IO; using System.Net; -using System.Text; + using BlubbFish.Utils; using BlubbFish.Utils.IoT.Bots; using BlubbFish.Utils.IoT.Connector; using BlubbFish.Utils.IoT.Events; + using Fraunhofer.Fit.IoT.LoraMap.Model; using Fraunhofer.Fit.IoT.LoraMap.Model.Admin; +using Fraunhofer.Fit.IoT.LoraMap.Model.Camera; +using Fraunhofer.Fit.IoT.LoraMap.Model.Position; +using Fraunhofer.Fit.IoT.LoraMap.Model.Sensor; +using Fraunhofer.Fit.IoT.LoraMap.Model.Svg; + using LitJson; namespace Fraunhofer.Fit.IoT.LoraMap { class Server : Webserver { - private readonly SortedDictionary positions = new SortedDictionary(); - private readonly SortedDictionary alarms = new SortedDictionary(); - private readonly SortedDictionary counter = new SortedDictionary(); - private readonly SortedDictionary density = new SortedDictionary(); - private readonly SortedDictionary fights = new SortedDictionary(); - private readonly SortedDictionary sensors = new SortedDictionary(); - private JsonData marker; - private readonly Settings settings; - private readonly WeatherWarnings weather; - private readonly Dictionary markertable = new Dictionary(); + private readonly SortedDictionary jsonapi = new SortedDictionary() { + { "camera", CameraModel.Instance }, + { "position", PositionModel.Instance }, + { "sensor", SensorModel.Instance }, + { "settings", Settings.Instance.External }, + }; private readonly AdminModel admin; - private readonly Object lockData = new Object(); - private readonly Object lockPanic = new Object(); - private readonly Object lockFight = new Object(); - private readonly Object lockCount = new Object(); - private readonly Object lockDensy = new Object(); - private readonly Object lockSensor = new Object(); public Server(ADataBackend backend, Dictionary settings) : base(backend, settings, null) { this.logger.SetPath(settings["loggingpath"]); - this.CheckJsonFiles(); this.admin = new AdminModel(settings); - this.marker = JsonMapper.ToObject(File.ReadAllText("json/names.json")); - this.admin.NamesUpdate += this.AdminModelUpdateNames; - this.settings = new Settings(); - this.weather = new WeatherWarnings(this.settings); - this.admin.SettingsUpdate += this.settings.AdminModelUpdateSettings; + this.admin.SettingsUpdate += Settings.Instance.ReloadSettings; + this.admin.GeoUpdate += Settings.Instance.ReloadGeo; + this.admin.NamesUpdate += PositionModel.Instance.ReloadNames; this.StartListen(); this.WaitForShutdown(); this.Dispose(); } - private void AdminModelUpdateNames(Object sender, EventArgs e) { - this.marker = JsonMapper.ToObject(File.ReadAllText("json/names.json")); - foreach(KeyValuePair item in this.positions) { - item.Value.UpdateMarker(this.marker, item.Key); - } - Console.WriteLine("Namen und Icons aktualisiert!"); - } - - private void CheckJsonFiles() { - if(!Directory.Exists("json")) { - _ = Directory.CreateDirectory("json"); - } - if(!File.Exists("json/names.json")) { - File.WriteAllText("json/names.json", "{}"); - } - if(!File.Exists("json/geo.json")) { - File.WriteAllText("json/geo.json", "{}"); - } - if (!File.Exists("json/settings.json")) { - File.WriteAllText("json/settings.json", "{}"); - } - } - protected override void Backend_MessageIncomming(Object sender, BackendEvent mqtt) { try { JsonData d = JsonMapper.ToObject(mqtt.Message); - if(((String)mqtt.From).Contains("lora/data") && PositionItem.CheckJson(d)) { - String name = PositionItem.GetId(d); - lock(this.lockData) { - if(this.positions.ContainsKey(name)) { - this.positions[name].Update(d); - } else { - this.positions.Add(name, new PositionItem(d, this.marker)); - } - } - Console.WriteLine("Koordinate erhalten!"); - } else if(((String)mqtt.From).Contains("lora/panic") && PositionItem.CheckJson(d)) { - String name = PositionItem.GetId(d); - lock(this.lockPanic) { - if(this.alarms.ContainsKey(name)) { - this.alarms[name].Update(d); - } else { - this.alarms.Add(name, new AlarmItem(d)); - } - } - lock(this.lockData) { - if(this.positions.ContainsKey(name)) { - this.positions[name].Update(d); - } else { - this.positions.Add(name, new PositionItem(d, this.marker)); - } - } - Console.WriteLine("PANIC erhalten!"); - } else if(((String)mqtt.From).Contains("camera/count") && Camera.CheckJson(d)) { - String cameraid = Camera.GetId(d); - lock(this.lockCount) { - if(this.counter.ContainsKey(cameraid)) { - this.counter[cameraid].Update(d); - } else { - this.counter.Add(cameraid, new Camera(d)); - } - } - } else if((((String)mqtt.From).Contains("sfn/crowd_density_local") || ((String)mqtt.From).Contains("camera/crowd")) && Crowd.CheckJsonCrowdDensityLocal(d) || ((String)mqtt.From).Contains("sfn/flow") && Crowd.CheckJsonFlow(d)) { - String cameraid = Crowd.GetId(d); - lock(this.lockDensy) { - if(this.density.ContainsKey(cameraid)) { - this.density[cameraid].Update(d); - } else { - this.density.Add(cameraid, new Crowd(d)); - } - } - } else if((((String)mqtt.From).Contains("camera/fighting_detection") || ((String)mqtt.From).Contains("sfn/fighting_detection")) && Fight.CheckJsonFightingDetection(d)) { - String cameraid = Fight.GetId(d); - lock(this.lockFight) { - if(this.fights.ContainsKey(cameraid)) { - this.fights[cameraid].Update(d); - } else { - this.fights.Add(cameraid, new Fight(d)); - } - } - } else if(((String)mqtt.From).Contains("lora/sensor") && EnviromentData.CheckJson(d)) { - String sensorid = EnviromentData.GetId(d); - lock(this.lockSensor) { - if(this.sensors.ContainsKey(sensorid)) { - this.sensors[sensorid].Update(d); - } else { - this.sensors.Add(sensorid, new EnviromentData(d)); - } - } - Console.WriteLine("Umweltdaten erhalten!"); - } + PositionModel.Instance.ParseMqttJson(d, (String)mqtt.From); + CameraModel.Instance.ParseMqttJson(d, (String)mqtt.From); + SensorModel.Instance.ParseMqttJson(d, (String)mqtt.From); } catch(Exception e) { Helper.WriteError("Backend_MessageIncomming(): "+e.Message + "\n\n" + e.StackTrace); } @@ -143,40 +50,24 @@ namespace Fraunhofer.Fit.IoT.LoraMap { protected override Boolean SendWebserverResponse(HttpListenerContext cont) { try { - if (cont.Request.Url.PathAndQuery.StartsWith("/get1000")) { - return SendJsonResponse(new Dictionary() { - { "loc", this.positions }, - { "panic", this.alarms }, - { "cameracount", this.counter }, - { "crowdcount", this.density }, - { "fightdedect", this.fights }, - { "weatherwarnings", this.weather.Warnungen }, - { "sensors", this.sensors } - }, cont); - } else if (cont.Request.Url.PathAndQuery.StartsWith("/get60000")) { - return SendJsonResponse(new Dictionary() { - { "currenttime", new Dictionary() { { "utc", DateTime.UtcNow } } } - }, cont); - } else if (cont.Request.Url.PathAndQuery.StartsWith("/getonce")) { - return SendJsonResponse(new Dictionary() { - { "getlayer", this.FindMapLayer() }, - { "getgeo", JsonMapper.ToObject(File.ReadAllText("json/geo.json")) }, - { "startup", this.settings } - }, cont); - } else if (cont.Request.Url.PathAndQuery.StartsWith("/icons/marker/Marker.svg") && cont.Request.Url.PathAndQuery.Contains("?")) { - String hash = cont.Request.Url.PathAndQuery.Substring(cont.Request.Url.PathAndQuery.IndexOf('?') + 1); - if (!this.markertable.ContainsKey(hash)) { - this.markertable.Add(hash, new Marker(hash)); + if(cont.Request.Url.AbsolutePath.StartsWith("/api/json/")) { + if(cont.Request.Url.AbsolutePath.Length > 10) { + String parts = cont.Request.Url.AbsolutePath[10..]; + Dictionary ret = new Dictionary(); + foreach(String part in parts.Split(",")) { + if(this.jsonapi.ContainsKey(part)) { + ret.Add(part, this.jsonapi[part]); + } + } + return SendJsonResponse(ret, cont); } - cont.Response.ContentType = "image/svg+xml"; - Byte[] buf = Encoding.UTF8.GetBytes(this.markertable[hash].ToString()); - cont.Response.ContentLength64 = buf.Length; - cont.Response.OutputStream.Write(buf, 0, buf.Length); - Console.WriteLine("200 - " + cont.Request.Url.PathAndQuery); - return true; - } else if (cont.Request.Url.PathAndQuery.StartsWith("/admin")) { + } else if(cont.Request.Url.AbsolutePath.StartsWith("/api/time")) { + return SendJsonResponse(new Dictionary() { { "utc", DateTime.UtcNow } }, cont); + } else if(cont.Request.Url.AbsolutePath.StartsWith("/api/svg/")) { + return SvgModel.Instance.ParseRequest(cont); + } else if(cont.Request.Url.PathAndQuery.StartsWith("/admin/")) { return this.admin.ParseReuqest(cont); - } else if (cont.Request.Url.PathAndQuery.StartsWith("/maps/")) { + } else if(cont.Request.Url.PathAndQuery.StartsWith("/maps/")) { return SendFileResponse(cont, "resources", false); } } catch(Exception e) { @@ -187,43 +78,8 @@ namespace Fraunhofer.Fit.IoT.LoraMap { return SendFileResponse(cont); } - private Dictionary> FindMapLayer() { - Dictionary> ret = new Dictionary> { - { "online", new Dictionary() { - { "title", "Online Map" }, - { "url", "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" }, - { "attribution", "© OpenStreetMap contributors" }, - { "minZoom", 1 }, - { "maxZoom", 19 } - } } - }; - if(Directory.Exists("resources" + Path.DirectorySeparatorChar + "maps")) { - String[] dirs = Directory.GetDirectories("resources" + Path.DirectorySeparatorChar + "maps"); - foreach(String dir in dirs) { - if(File.Exists(dir + Path.DirectorySeparatorChar + "tiles.json")) { - try { - JsonData map = JsonMapper.ToObject(File.ReadAllText(dir + Path.DirectorySeparatorChar + "tiles.json")); - Dictionary entry = new Dictionary { - { "title", (String)map["name"] }, - { "url", (String)map["tiles"][0] }, - { "attribution", (String)map["attribution"] }, - { "minZoom", (Int32)map["minzoom"] }, - { "maxZoom", (Int32)map["maxzoom"] }, - { "bounds", new Dictionary() { - { "corner1", new Double[] { (Double)map["bounds"][0], (Double)map["bounds"][1] } }, - { "corner2", new Double[] { (Double)map["bounds"][2], (Double)map["bounds"][3] } } - } } - }; - ret.Add(dir.Substring(("resources" + Path.DirectorySeparatorChar + "maps").Length+1), entry); - } catch { } - } - } - } - return ret; - } - public override void Dispose() { - this.weather.Dispose(); + SensorModel.Instance.Dispose(); base.Dispose(); } } diff --git a/Lora-Map/resources/admin/index.html b/Lora-Map/resources/admin/index.html index 1632311..3712a2e 100644 --- a/Lora-Map/resources/admin/index.html +++ b/Lora-Map/resources/admin/index.html @@ -5,7 +5,6 @@ Adminpannel Lora-Map - @@ -18,5 +17,9 @@
Wilkommen im Adminbereich
+ + + + \ No newline at end of file diff --git a/Lora-Map/resources/admin/js/adminmenu.js b/Lora-Map/resources/admin/js/adminmenu.js new file mode 100644 index 0000000..7946d88 --- /dev/null +++ b/Lora-Map/resources/admin/js/adminmenu.js @@ -0,0 +1,42 @@ +var AdminMenu = { + //public functions + ExImport: function () { + var ajaxrequest = new XMLHttpRequest(); + ajaxrequest.onreadystatechange = function () { + if (ajaxrequest.readyState === 4 && ajaxrequest.status === 200) { + var json = JSON.parse(ajaxrequest.responseText); + ExImport.ParseJson(json.name, json.geo, json.setting); + } + }; + ajaxrequest.open("GET", "/admin/api/json/name,geo,setting", true); + ajaxrequest.send(); + return false; + }, + Names: function () { + var ajaxrequest = new XMLHttpRequest(); + ajaxrequest.onreadystatechange = function () { + if (ajaxrequest.readyState === 4 && ajaxrequest.status === 200) { + var json = JSON.parse(ajaxrequest.responseText); + NamesEditor.ParseJson(json.name); + } + }; + ajaxrequest.open("GET", "/admin/api/json/name", true); + ajaxrequest.send(); + return false; + }, + Overlay: function () { + return false; + }, + Settings: function () { + var ajaxrequest = new XMLHttpRequest(); + ajaxrequest.onreadystatechange = function () { + if (ajaxrequest.readyState === 4 && ajaxrequest.status === 200) { + var json = JSON.parse(ajaxrequest.responseText); + Settings.ParseJson(json.setting); + } + }; + ajaxrequest.open("GET", "/admin/api/json/setting", true); + ajaxrequest.send(); + return false; + } +}; \ No newline at end of file diff --git a/Lora-Map/resources/admin/js/eximport.js b/Lora-Map/resources/admin/js/eximport.js new file mode 100644 index 0000000..6af041c --- /dev/null +++ b/Lora-Map/resources/admin/js/eximport.js @@ -0,0 +1,56 @@ +var ExImport = { + //public functions + ParseJson: function (jsonnames, jsongeo, jsonsettings) { + html = "
Ex- und Import der Einstellungen
"; + html += "
names.json (Namen und Icons)
"; + html += "
geo.json (Layer on the MAP) Kml Konverter
"; + html += "
settings.json (Settings of the Map)
"; + html += "
"; + document.getElementById("content").innerHTML = html; + document.getElementById("ex_names").value = JSON.stringify(jsonnames); + document.getElementById("ex_geo").value = JSON.stringify(jsongeo); + document.getElementById("ex_settings").value = JSON.stringify(jsonsettings); + }, + SaveNames: function () { + var savenames = new XMLHttpRequest(); + savenames.onreadystatechange = function () { + if (savenames.readyState === 4) { + if (savenames.status === 200) { + alert("Änderungen an names.json gespeichert!"); + } else if (savenames.status === 501) { + alert("Ein Fehler ist aufgetreten (invalid JSON)!"); + } + } + }; + savenames.open("PUT", "/admin/api/json/name", true); + savenames.send(document.getElementById("ex_names").value); + }, + SaveGeo: function () { + var savegeo = new XMLHttpRequest(); + savegeo.onreadystatechange = function () { + if (savegeo.readyState === 4) { + if (savegeo.status === 200) { + alert("Änderungen an geo.json gespeichert!"); + } else if (savegeo.status === 501) { + alert("Ein Fehler ist aufgetreten (invalid JSON)!"); + } + } + }; + savegeo.open("PUT", "/admin/api/json/geo", true); + savegeo.send(document.getElementById("ex_geo").value); + }, + SaveSettings: function () { + var savesettings = new XMLHttpRequest(); + savesettings.onreadystatechange = function () { + if (savesettings.readyState === 4) { + if (savesettings.status === 200) { + alert("Änderungen an settings.json gespeichert!"); + } else if (savesettings.status === 501) { + alert("Ein Fehler ist aufgetreten (invalid JSON)!"); + } + } + }; + savesettings.open("PUT", "/admin/api/json/setting", true); + savesettings.send(document.getElementById("ex_settings").value); + } +}; \ No newline at end of file diff --git a/Lora-Map/resources/admin/js/menu.js b/Lora-Map/resources/admin/js/menu.js deleted file mode 100644 index 704d969..0000000 --- a/Lora-Map/resources/admin/js/menu.js +++ /dev/null @@ -1,741 +0,0 @@ -var AdminMenu = { - Names: function () { - var ajaxnames = new XMLHttpRequest(); - ajaxnames.onreadystatechange = function () { - if (ajaxnames.readyState === 4 && ajaxnames.status === 200) { - NamesEditor.ParseJson(ajaxnames.responseText); - } - }; - ajaxnames.open("GET", "/admin/get_json_names", true); - ajaxnames.send(); - return false; - }, - Overlay: function () { - return false; - }, - Settings: function () { - var ajaxsettings = new XMLHttpRequest(); - ajaxsettings.onreadystatechange = function () { - if (ajaxsettings.readyState === 4 && ajaxsettings.status === 200) { - Settings.ParseJson(JSON.parse(ajaxsettings.responseText)); - } - }; - ajaxsettings.open("GET", "/admin/get_json_settings", true); - ajaxsettings.send(); - return false; - }, - ExImport: function () { - var ajaxnames = new XMLHttpRequest(); - ajaxnames.onreadystatechange = function () { - if (ajaxnames.readyState === 4 && ajaxnames.status === 200) { - var ajaxgeo = new XMLHttpRequest(); - ajaxgeo.onreadystatechange = function () { - if (ajaxgeo.readyState === 4 && ajaxgeo.status === 200) { - var ajaxsettings = new XMLHttpRequest(); - ajaxsettings.onreadystatechange = function () { - if (ajaxsettings.readyState === 4 && ajaxsettings.status === 200) { - ExImport.ParseJson(ajaxnames.responseText, ajaxgeo.responseText, ajaxsettings.responseText); - } - }; - ajaxsettings.open("GET", "/admin/get_json_settings", true); - ajaxsettings.send(); - } - }; - ajaxgeo.open("GET", "/admin/get_json_geo", true); - ajaxgeo.send(); - } - }; - ajaxnames.open("GET", "/admin/get_json_names", true); - ajaxnames.send(); - return false; - } -}; - -var NamesEditor = { - iconeditorcounter: 0, - filterGropus: { no: "immer Sichtbar", fw: "Feuerwehr", sani: "Sanitäter", pol: "Polizei", oa: "Ordnungsamt", si: "Sicherheitsdienst", thw: "Technisches Hilfswerk", crew: "Veranstalter", dev: "Entwickler" }, - ParseJson: function (jsontext) { - document.getElementById("content").innerHTML = ""; - var namesconfig = JSON.parse(jsontext); - var html = "
Namenseinträge in den Einstellungen
"; - html += ""; - html += ""; - html += ""; - for (var id in namesconfig) { - if (namesconfig.hasOwnProperty(id)) { - var nameentry = namesconfig[id]; - html += "" + - "" + - ""; - if (nameentry.hasOwnProperty("marker.svg")) { - html += ""; - } else if (nameentry.hasOwnProperty("icon")) { - html += ""; - } else { - html += ""; - } - var gfilter = typeof nameentry.Group === "undefined" ? "no" : nameentry.Group; - html += ""; - html += "" + - ""; - } - } - html += ""; - html += ""; - html += "
IDNameIconFilter Gruppe
" + id + "" + nameentry["name"] + "" + this.ParseIcon(nameentry["marker.svg"]) + "" + this.filterGropus[gfilter] + "
"; - document.getElementById("content").innerHTML = html + "
"; - }, - ParseIcon: function (markerobj) { - var url = "../icons/marker/Marker.svg"; - if (markerobj.hasOwnProperty("person")) { - url += "?icon=person&marker-bg=hidden"; - if (markerobj["person"].hasOwnProperty("org")) { - url += "&person-org=" + markerobj["person"]["org"]; - } - if(markerobj["person"].hasOwnProperty("funct")) { - url += "&person-funct=" + markerobj["person"]["funct"]; - } - if(markerobj["person"].hasOwnProperty("rang")) { - url += "&person-rang=" + markerobj["person"]["rang"]; - } - if(markerobj["person"].hasOwnProperty("text")) { - url += "&person-text=" + markerobj["person"]["text"]; - } - if (markerobj["person"].hasOwnProperty("typ") && Array.isArray(markerobj["person"]["typ"])) { - for (i in markerobj["person"]["typ"]) { - url += "&person-typ=" + markerobj["person"]["typ"][i]; - } - } - } - return ""; - }, - BuildIconJson: function (url) { - var query = this.SplitQueryIntoObject(this.SplitUrlIntoParts(url).query); - var markerobj = {}; - if (query.hasOwnProperty("icon") && query["icon"] === "person") { - markerobj["person"] = {}; - if (query.hasOwnProperty("person-org")) { - markerobj["person"]["org"] = query["person-org"]; - } - if (query.hasOwnProperty("person-funct")) { - markerobj["person"]["funct"] = query["person-funct"]; - } - if (query.hasOwnProperty("person-rang")) { - markerobj["person"]["rang"] = query["person-rang"]; - } - if (query.hasOwnProperty("person-text")) { - markerobj["person"]["text"] = query["person-text"]; - } - if (query.hasOwnProperty("person-typ")) { - if (Array.isArray(query["person-typ"])) { - markerobj["person"]["typ"] = new Array(); - for (var i in query["person-typ"]) { - markerobj["person"]["typ"].push(query["person-typ"][i]); - } - } else { - markerobj["person"]["typ"] = new Array(); - markerobj["person"]["typ"].push(query["person-typ"]); - } - } - } - return markerobj; - }, - Add: function () { - var newrow = document.createElement("tr"); - newrow.innerHTML = ""; - newrow.innerHTML += ""; - newrow.innerHTML += " wähle Icon"; - newrow.innerHTML += "" + this.CreateSelectBox("", "item", { item: "" }, this.filterGropus, null, null, true); - newrow.innerHTML += " "; - document.getElementById("nametable").children[1].appendChild(newrow); - }, - Save: function () { - var rows = document.getElementById("nametable").children[1].children; - var namejson = {}; - for (var i = 0; i < rows.length; i++) { - if (rows[i].children[0].children.length === 1) { - alert("Bitte zuerst alle Zeilen speichern oder Löschen!"); - return; - } - var id = rows[i].children[0].innerText; - var name = rows[i].children[1].innerText; - namejson[id] = { "name": name, "Group": rows[i].children[3].attributes.rel.nodeValue }; - if (rows[i].children[2].children[0].hasAttribute("data")) { - namejson[id]["marker.svg"] = this.BuildIconJson(rows[i].children[2].children[0].data); - } - } - var savenames = new XMLHttpRequest(); - savenames.onreadystatechange = function () { - if (savenames.readyState === 4) { - if (savenames.status === 200) { - alert("Änderungen gespeichert!"); - } else if (savenames.status === 501) { - alert("Ein Fehler ist aufgetreten (invalid JSON)!"); - } - } - }; - savenames.open("POST", "/admin/set_json_names", true); - savenames.send(JSON.stringify(namejson)); - }, - Delete: function (el) { - var name = el.firstChild.innerHTML; - var answ = window.prompt("Wollen sie den Eintrag für \"" + name + "\" wirklich löschen?", ""); - if (answ !== null) { - el.parentNode.removeChild(el); - } - }, - Edit: function (el) { - var id = el.children[0].innerText; - var name = el.children[1].innerText; - var url = null; - var gfilter = el.children[3].attributes.rel.nodeValue; - if (el.children[2].children[0].hasAttribute("data")) { - url = el.children[2].children[0].data; - } - el.innerHTML = ""; - el.innerHTML += ""; - if (url === null) { - el.innerHTML += " wähle Icon"; - } else { - el.innerHTML += " "; - } - el.innerHTML += "" + this.CreateSelectBox("", "item", { item: gfilter }, this.filterGropus, null, null, true); - el.innerHTML += " "; - }, - Abort: function (el) { - el.parentNode.removeChild(el); - }, - SaveRow: function (el) { - var id = el.children[0].children[0].value; - var name = el.children[1].children[0].value; - var url = null; - var gfilter = el.children[3].children[0].selectedOptions[0].value; - if (gfilter === "---") { - gfilter = "no"; - } - if (el.children[2].children.length === 2) { - url = el.children[2].children[1].data; - } - el.innerHTML = "" + id + "" + - "" + name + ""; - if (url === null) { - el.innerHTML += ""; - } else { - el.innerHTML += ""; - } - el.innerHTML += "" + this.filterGropus[gfilter] + ""; - el.innerHTML += " "; - }, - IconEditor: function (el) { - var url = "../icons/marker/Marker.svg?marker-bg=hidden"; - el.id = "icon_edit_" + this.iconeditorcounter++; - if (el.children.length === 2) { - url = el.children[1].data; - } - var query = this.SplitQueryIntoObject(this.SplitUrlIntoParts(url).query); - var ie = document.createElement("div"); - ie.id = "iconeditor"; - ie.innerHTML = "
" + - "
" + - "
" + - this.CreateSelectBox("Typ", "icon", query, { "person": "Person" }, null, "iconeditor-type-") + "
" + - "
" + - this.CreateSelectBox("Organisation", "person-org", query, { "fw": "Feuerwehr", "thw": "Technisches Hilfswerk", "hilo": "Hilfsorganisationen, Bundeswehr", "fueh": "Einrichtungen der Führung", "pol": "Polizei, Bundespolizei, Zoll", "sonst": "Sonstige Einrichtungen der Gefahrenabwehr" }) + "
" + - this.CreateSelectBox("Funktion", "person-funct", query, { "sonder": "Sonder", "fueh": "Führung" }) + "
" + - this.CreateSelectBox("Rang", "person-rang", query, { "trupp": "Trupp", "grupp": "Gruppe", "zug":"Zug" }) + "
" + - "Text:
" + - this.CreateSelectBox("Typ", "person-typ", query, { "loesch": "Brandbekämpfung/Löscheinsatz", "sani": "Rettungswesen, Sanitätswesen, Gesundheitswesen", "betreu": "Betreuung" }, true) + "
" + - "
" + - "
" + - "
" + - "
"; - document.getElementsByTagName("body")[0].appendChild(ie); - }, - CreateSelectBox: function (title, key, query, options, muliple, group, noonchange) { - var html = title !== "" ? title + ": " : ""; - var onchange = ""; - if (!(typeof noonchange !== "undefined" && noonchange === true)) { - var eventtext = "NamesEditor.ChangeLinkPreview(\"" + key + "\",this.selectedOptions);"; - if (typeof group !== "undefined" && group !== null) { - eventtext += " document.getElementById(\"" + group + "\"+this.value).style.display = \"block\";'"; - } - onchange = " onchange='" + eventtext + "'"; - } - html += ""; - if (typeof muliple === "undefined" || muliple === null) { - html += ""; - } - for (var value in options) { - if (query.hasOwnProperty(key) && query[key] === value) { - html += ""; - } else if (query.hasOwnProperty(key) && Array.isArray(query[key])) { - var notinqueryarray = true; - for (var i in query[key]) { - if (query[key][i] === value) { - notinqueryarray = false; - html += ""; - } - } - if (notinqueryarray) { - html += ""; - } - } else { - html += ""; - } - } - html += ""; - return html; - }, - SaveIconEditor: function (id) { - var cell = document.getElementById(id); - cell.innerHTML = " "; - cell.removeAttribute("id"); - document.getElementById("iconeditor").remove(); - }, - SplitQueryIntoObject: function (query) { - if (query.indexOf("?") !== -1) { - query = query.split("?")[1]; - } - var queryobj = {}; - var pairs = query.split("&"); - for (var i = 0; i < pairs.length; i++) { - var pair = pairs[i].split("="); - if (queryobj.hasOwnProperty(decodeURIComponent(pair[0]))) { - if (Array.isArray(queryobj[decodeURIComponent(pair[0])])) { - queryobj[decodeURIComponent(pair[0])].push(decodeURIComponent(pair[1] || "")); - } else { - var tmp = queryobj[decodeURIComponent(pair[0])]; - queryobj[decodeURIComponent(pair[0])] = new Array(); - queryobj[decodeURIComponent(pair[0])].push(tmp); - queryobj[decodeURIComponent(pair[0])].push(decodeURIComponent(pair[1] || "")); - } - } else { - queryobj[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || ""); - } - } - return queryobj; - }, - JoinObjectIntoQuery: function (queryobj) { - var query = new Array(); - for (var id in queryobj) { - if (Array.isArray(queryobj[id])) { - for (var i in queryobj[id]) { - query.push(encodeURIComponent(id) + "=" + encodeURIComponent(queryobj[id][i])); - } - } else { - query.push(encodeURIComponent(id) + "=" + encodeURIComponent(queryobj[id])); - } - } - return query.join("&"); - }, - SplitUrlIntoParts: function (url) { - var parts = url.split("?"); - return { "file": parts[0], "query": parts[1] || "" }; - }, - ChangeLinkPreview: function (key, val) { - var cur = this.SplitUrlIntoParts(document.getElementById("markerprev").data); - var query = this.SplitQueryIntoObject(cur.query); - if (typeof val === "object") { - query[key] = new Array(); - for (var i = 0; i < val.length; i++) { - query[key].push(val[i].value); - if (val[i].value === "---") { - delete query[key]; - break; - } - } - } else { - if (val === "---" || val === "") { - delete query[key]; - } else { - query[key] = val; - } - } - document.getElementById("markerprev").data = cur.file + "?" + this.JoinObjectIntoQuery(query); - } -}; - -var Settings = { - ParseJson: function (jsonsettings) { - if (typeof jsonsettings.StartPos === "undefined") { - jsonsettings.StartPos = { lat: 0, lon: 0 }; - } - if (typeof jsonsettings.CellIds === "undefined") { - jsonsettings.CellIds = []; - } - if (typeof jsonsettings.GridRadius === "undefined") { - jsonsettings.GridRadius = 1000; - } - if (typeof jsonsettings.FightDedection === "undefined") { - jsonsettings.FightDedection = []; - } - if (typeof jsonsettings.CrwodDensity === "undefined") { - jsonsettings.CrwodDensity = []; - } - if (typeof jsonsettings.Counting === "undefined") { - jsonsettings.Counting = []; - } - if (typeof jsonsettings.Sensors === "undefined") { - jsonsettings.Sensors = []; - } - var html = "
Einstellungen
"; - html += "
Startpunkt: Lat, Lon
"; - html += "
CellId's für DWD-Wetterwarnungen: (Trennen durch \";\", cap_warncellids_csv)
"; - html += "
Radius für das Grid um den Startpunkt: m
"; - html += "
Fight Dedection Kameras:
" + this._renderFightDedection(jsonsettings.FightDedection) + "
"; - html += "
Crowd Density Kameras:
" + this._renderCrowdDensity(jsonsettings.CrwodDensity) + "
"; - html += "
Sensors:
" + this._renderSensorSettings(jsonsettings.Sensors) + "
"; - html += "
"; - document.getElementById("content").innerHTML = html + "
"; - }, - Save: function () { - var ret = {}; - ret.StartPos = {}; - ret.StartPos.lat = parseFloat(document.getElementById("startlat").value.replace(",", ".")); - ret.StartPos.lon = parseFloat(document.getElementById("startlon").value.replace(",", ".")); - ret.CellIds = document.getElementById("wetterids").value.split(";"); - ret.GridRadius = parseInt(document.getElementById("gridrad").value); - - var rowsf = document.getElementById("fighttable").children[1].children; - var fightjson = {}; - for (var i = 0; i < rowsf.length; i++) { - if (rowsf[i].children[0].children.length === 1) { - alert("Bitte zuerst alle Zeilen speichern oder Löschen!"); - return; - } - var id = rowsf[i].children[0].innerText; - var coords = rowsf[i].children[1].innerHTML.split("
"); - var polyjson = []; - for (var j = 0; j < coords.length; j++) { - var coord = coords[j].split(";"); - polyjson[j] = { "Lat": this._filterFloat(coord[0]), "Lon": this._filterFloat(coord[1]) }; - } - fightjson[id] = { "Poly": polyjson, "Alias": rowsf[i].children[2].innerText, "Level": this._filterFloat(rowsf[i].children[3].innerText) }; - } - ret.FightDedection = fightjson; - - var rowsc = document.getElementById("crowdtable").children[1].children; - var crowdjson = {}; - for (i = 0; i < rowsc.length; i++) { - if (rowsc[i].children[0].children.length === 1) { - alert("Bitte zuerst alle Zeilen speichern oder Löschen!"); - return; - } - id = rowsc[i].children[0].innerText; - var num = this._filterFloat(rowsc[i].children[1].innerText); - coords = rowsc[i].children[2].innerHTML.split("
"); - - polyjson = []; - for (j = 0; j < coords.length; j++) { - coord = coords[j].split(";"); - polyjson[j] = { "Lat": this._filterFloat(coord[0]), "Lon": this._filterFloat(coord[1]) }; - } - crowdjson[id] = { - "Poly": polyjson, - "Count": num, - "Alias": rowsc[i].children[3].innerText - }; - } - ret.CrwodDensity = crowdjson; - - var rowss = document.getElementById("sensortable").children[1].children; - var sensorjson = {}; - for (i = 0; i < rowss.length; i++) { - if (rowss[i].children[0].children.length === 1) { - alert("Bitte zuerst alle Zeilen speichern oder Löschen!"); - return; - } - id = rowss[i].children[0].innerText; - coord = rowss[i].children[2].innerHTML.split(";"); - sensorjson[id] = { - "Poly": { - "Lat": this._filterFloat(coord[0]), - "Lon": this._filterFloat(coord[1]) - }, - "Level": this._filterFloat(rowss[i].children[3].innerText), - "Alias": rowss[i].children[1].innerText - }; - } - ret.Sensors = sensorjson; - - var savesettings = new XMLHttpRequest(); - savesettings.onreadystatechange = function () { - if (savesettings.readyState === 4) { - if (savesettings.status === 200) { - alert("Änderungen gespeichert!"); - } else if (savesettings.status === 501) { - alert("Ein Fehler ist aufgetreten (invalid JSON)!"); - } - } - }; - savesettings.open("POST", "/admin/set_json_settings", true); - savesettings.send(JSON.stringify(ret)); - }, - _renderSensorSettings: function (json) { - var ret = ""; - ret += ""; - ret += ""; - - ret += ""; - for (var id in json) { - ret += "" + - "" + - "" + - "" + - "" + - "" + - ""; - } - ret += ""; - - ret += ""; - ret += "
IDAliasKoordinatenWarn above
" + id + "" + json[id].Alias + "" + json[id].Poly.Lat + ";" + json[id].Poly.Lon + "" + json[id].Level + "
"; - return ret; - }, - _renderFightDedection: function (json) { - var ret = ""; - ret += ""; - ret += ""; - ret += ""; - for (var id in json) { - var coords = []; - for (var i = 0; i < json[id].Poly.length; i++) { - coords[i] = json[id].Poly[i].Lat + ";" + json[id].Poly[i].Lon; - } - ret += "" + - "" + - "" + - "" + - "" + - "" + - ""; - } - ret += ""; - ret += ""; - ret += "
IDKoordinatenAliasAlertlimit
" + id + "" + coords.join("
") + "
" + json[id].Alias + "" + json[id].Level + "
"; - return ret; - }, - _renderCrowdDensity: function (json) { - var ret = ""; - ret += ""; - ret += ""; - ret += ""; - for (var id in json) { - var coords = []; - for (var i = 0; i < json[id].Poly.length; i++) { - coords[i] = json[id].Poly[i].Lat + ";" + json[id].Poly[i].Lon; - } - ret += "" + - "" + - "" + - "" + - "" + - "" + - ""; - } - ret += ""; - ret += ""; - ret += "
IDPersonenanzahlKoordinatenAlias
" + id + "" + json[id].Count + "" + coords.join("
") + "
" + json[id].Alias + "
"; - return ret; - }, - AddSensor: function () { - var newrow = document.createElement("tr"); - newrow.innerHTML = ""; - newrow.innerHTML += ""; - newrow.innerHTML += ""; - newrow.innerHTML += ""; - newrow.innerHTML += " "; - document.getElementById("sensortable").children[1].appendChild(newrow); - }, - AddFight: function () { - var newrow = document.createElement("tr"); - newrow.innerHTML = ""; - newrow.innerHTML += ""; - newrow.innerHTML += ""; - newrow.innerHTML += ""; - newrow.innerHTML += " "; - document.getElementById("fighttable").children[1].appendChild(newrow); - }, - AddDensity: function () { - var newrow = document.createElement("tr"); - newrow.innerHTML = ""; - newrow.innerHTML += ""; - newrow.innerHTML += ""; - newrow.innerHTML += ""; - newrow.innerHTML += " "; - document.getElementById("crowdtable").children[1].appendChild(newrow); - }, - Abort: function (el) { - el.parentNode.removeChild(el); - }, - SaveRowSensor: function (el) { - var coords = el.children[2].children[0].value; - var coord = coords.split(";"); - var fail = false; - if (coord.length !== 2) { - fail = true; - } else if (isNaN(this._filterFloat(coord[0])) || isNaN(this._filterFloat(coord[1]))) { - fail = true; - } - if (isNaN(this._filterFloat(el.children[3].children[0].value))) { - alert("Die Eingabe des Alertlevel erwartet einen Float"); - return; - } - if (fail) { - alert("Die Eingabe der Koordinaten ist nicht Korrekt!\n\nBeispiel:\n50.7;7.8"); - return; - } - el.innerHTML = "" + el.children[0].children[0].value + "" + - "" + el.children[1].children[0].value + "" + - "" + coords + "" + - "" + this._filterFloat(el.children[3].children[0].value) + "" + - " "; - }, - SaveRowfight: function (el) { - var coords = el.children[1].children[0].value.replace(/\n/gi, "
"); - var coordscheck = coords.split("
"); - var fail = false; - for (var i = 0; i < coordscheck.length; i++) { - var coord = coordscheck[i].split(";"); - if (coord.length !== 2) { - fail = true; - break; - } - if (isNaN(this._filterFloat(coord[0])) || isNaN(this._filterFloat(coord[1]))) { - fail = true; - break; - } - } - if (isNaN(this._filterFloat(el.children[3].children[0].value))) { - alert("Die Eingabe des Alertlevel erwartet einen Float"); - return; - } - if (fail) { - alert("Die Eingabe der Koordinaten ist nicht Korrekt!\n\nBeispiel:\n50.7;7.8\n50.6;7.9"); - return; - } - el.innerHTML = "" + el.children[0].children[0].value + "" + - "" + coords + "" + - "" + el.children[2].children[0].value + "" + - "" + this._filterFloat(el.children[3].children[0].value) + "" + - " "; - }, - SaveRowdensity: function (el) { - var coords = el.children[2].children[0].value.replace(/\n/gi, "
"); - var coordscheck = coords.split("
"); - var fail = false; - for (var i = 0; i < coordscheck.length; i++) { - var coord = coordscheck[i].split(";"); - if (coord.length !== 2) { - fail = true; - break; - } - if (isNaN(this._filterFloat(coord[0])) || isNaN(this._filterFloat(coord[1]))) { - fail = true; - break; - } - } - if (fail) { - alert("Die Eingabe der Koordinaten ist nicht Korrekt!\n\nBeispiel:\n50.7;7.8\n50.6;7.9"); - return; - } - if (isNaN(this._filterFloat(el.children[1].children[0].value))) { - alert("Die Eingabe der Maximalen Anzahl der Personen ist nicht Korrekt, erwarte eine Zahl."); - return; - } - el.innerHTML = "" + el.children[0].children[0].value + "" + - "" + el.children[1].children[0].value + "" + - "" + coords + "" + - "" + el.children[3].children[0].value + "" + - " "; - }, - Delete: function (el) { - var answ = window.prompt("Wollen sie den Eintrag für \"" + el.firstChild.innerHTML + "\" wirklich löschen?", ""); - if (answ !== null) { - el.parentNode.removeChild(el); - } - }, - EditSensor: function (el) { - el.innerHTML = "" + - "" + - "" + - "" + - " "; - }, - EditFight: function (el) { - el.innerHTML = "" + - "" + - "" + - "" + - " "; - }, - EditDensity: function (el) { - el.innerHTML = "" + - "" + - "" + - "" + - " "; - }, - _filterFloat: function (value) { - if (/^(\-|\+)?([0-9]+(\.[0-9]+)?|Infinity)$/.test(value)) { - return Number(value); - } - return NaN; - } -}; - -var ExImport = { - ParseJson: function (jsonnames, jsongeo, jsonsettings) { - html = "
Ex- und Import der Einstellungen
"; - html += "
names.json (Namen und Icons)
"; - html += "
geo.json (Layer on the MAP) Kml Konverter
"; - html += "
settings.json (Settings of the Map)
"; - html += "
"; - document.getElementById("content").innerHTML = html; - document.getElementById("ex_names").value = jsonnames; - document.getElementById("ex_geo").value = jsongeo; - document.getElementById("ex_settings").value = jsonsettings; - }, - SaveNames: function () { - var savenames = new XMLHttpRequest(); - savenames.onreadystatechange = function () { - if (savenames.readyState === 4) { - if (savenames.status === 200) { - alert("Änderungen an names.json gespeichert!"); - } else if (savenames.status === 501) { - alert("Ein Fehler ist aufgetreten (invalid JSON)!"); - } - } - }; - savenames.open("POST", "/admin/set_json_names", true); - savenames.send(document.getElementById("ex_names").value); - }, - SaveGeo: function () { - var savegeo = new XMLHttpRequest(); - savegeo.onreadystatechange = function () { - if (savegeo.readyState === 4) { - if (savegeo.status === 200) { - alert("Änderungen an geo.json gespeichert!"); - } else if (savegeo.status === 501) { - alert("Ein Fehler ist aufgetreten (invalid JSON)!"); - } - } - }; - savegeo.open("POST", "/admin/set_json_geo", true); - savegeo.send(document.getElementById("ex_geo").value); - }, - SaveSettings: function () { - var savesettings = new XMLHttpRequest(); - savesettings.onreadystatechange = function () { - if (savesettings.readyState === 4) { - if (savesettings.status === 200) { - alert("Änderungen an settings.json gespeichert!"); - } else if (savesettings.status === 501) { - alert("Ein Fehler ist aufgetreten (invalid JSON)!"); - } - } - }; - savesettings.open("POST", "/admin/set_json_settings", true); - savesettings.send(document.getElementById("ex_settings").value); - } -}; \ No newline at end of file diff --git a/Lora-Map/resources/admin/js/nameseditor.js b/Lora-Map/resources/admin/js/nameseditor.js new file mode 100644 index 0000000..a0a33d7 --- /dev/null +++ b/Lora-Map/resources/admin/js/nameseditor.js @@ -0,0 +1,304 @@ +var NamesEditor = { + //public variables + iconeditorcounter: 0, + filterGropus: { no: "immer Sichtbar", fw: "Feuerwehr", sani: "Sanitäter", pol: "Polizei", oa: "Ordnungsamt", si: "Sicherheitsdienst", thw: "Technisches Hilfswerk", crew: "Veranstalter", dev: "Entwickler" }, + //public functions + Abort: function (el) { + el.parentNode.removeChild(el); + }, + Add: function () { + var newrow = document.createElement("tr"); + newrow.innerHTML = ""; + newrow.innerHTML += ""; + newrow.innerHTML += " wähle Icon"; + newrow.innerHTML += "" + this.CreateSelectBox("", "item", { item: "" }, this.filterGropus, null, null, true); + newrow.innerHTML += " "; + document.getElementById("nametable").children[1].appendChild(newrow); + }, + BuildIconJson: function (url) { + var query = this.SplitQueryIntoObject(this.SplitUrlIntoParts(url).query); + var markerobj = {}; + if (Object.prototype.hasOwnProperty.call(query, "icon") && query["icon"] === "person") { + markerobj["person"] = {}; + if (Object.prototype.hasOwnProperty.call(query, "person-org")) { + markerobj["person"]["org"] = query["person-org"]; + } + if (Object.prototype.hasOwnProperty.call(query, "person-funct")) { + markerobj["person"]["funct"] = query["person-funct"]; + } + if (Object.prototype.hasOwnProperty.call(query, "person-rang")) { + markerobj["person"]["rang"] = query["person-rang"]; + } + if (Object.prototype.hasOwnProperty.call(query, "person-text")) { + markerobj["person"]["text"] = query["person-text"]; + } + if (Object.prototype.hasOwnProperty.call(query, "person-typ")) { + if (Array.isArray(query["person-typ"])) { + markerobj["person"]["typ"] = new Array(); + for (var i in query["person-typ"]) { + markerobj["person"]["typ"].push(query["person-typ"][i]); + } + } else { + markerobj["person"]["typ"] = new Array(); + markerobj["person"]["typ"].push(query["person-typ"]); + } + } + } + return markerobj; + }, + ChangeLinkPreview: function (key, val) { + var cur = this.SplitUrlIntoParts(document.getElementById("markerprev").data); + var query = this.SplitQueryIntoObject(cur.query); + if (typeof val === "object") { + query[key] = new Array(); + for (var i = 0; i < val.length; i++) { + query[key].push(val[i].value); + if (val[i].value === "---") { + delete query[key]; + break; + } + } + } else { + if (val === "---" || val === "") { + delete query[key]; + } else { + query[key] = val; + } + } + document.getElementById("markerprev").data = cur.file + "?" + this.JoinObjectIntoQuery(query); + }, + CreateSelectBox: function (title, key, query, options, muliple, group, noonchange) { + var html = title !== "" ? title + ": " : ""; + var onchange = ""; + if (!(typeof noonchange !== "undefined" && noonchange === true)) { + var eventtext = "NamesEditor.ChangeLinkPreview(\"" + key + "\",this.selectedOptions);"; + if (typeof group !== "undefined" && group !== null) { + eventtext += " document.getElementById(\"" + group + "\"+this.value).style.display = \"block\";'"; + } + onchange = " onchange='" + eventtext + "'"; + } + html += ""; + if (typeof muliple === "undefined" || muliple === null) { + html += ""; + } + for (var value in options) { + if (Object.prototype.hasOwnProperty.call(query, key) && query[key] === value) { + html += ""; + } else if (Object.prototype.hasOwnProperty.call(query, key) && Array.isArray(query[key])) { + var notinqueryarray = true; + for (var i in query[key]) { + if (query[key][i] === value) { + notinqueryarray = false; + html += ""; + } + } + if (notinqueryarray) { + html += ""; + } + } else { + html += ""; + } + } + html += ""; + return html; + }, + Delete: function (el) { + var name = el.firstChild.innerHTML; + var answ = window.prompt("Wollen sie den Eintrag für \"" + name + "\" wirklich löschen?", ""); + if (answ !== null) { + el.parentNode.removeChild(el); + } + }, + Edit: function (el) { + var id = el.children[0].innerText; + var name = el.children[1].innerText; + var url = null; + var gfilter = el.children[3].attributes.rel.nodeValue; + if (el.children[2].children[0].hasAttribute("data")) { + url = el.children[2].children[0].data; + } + el.innerHTML = ""; + el.innerHTML += ""; + if (url === null) { + el.innerHTML += " wähle Icon"; + } else { + el.innerHTML += " "; + } + el.innerHTML += "" + this.CreateSelectBox("", "item", { item: gfilter }, this.filterGropus, null, null, true); + el.innerHTML += " "; + }, + IconEditor: function (el) { + var url = "../api/svg/person.svg?"; + el.id = "icon_edit_" + this.iconeditorcounter++; + if (el.children.length === 2) { + url = el.children[1].data; + } + var query = this.SplitQueryIntoObject(this.SplitUrlIntoParts(url).query); + var ie = document.createElement("div"); + ie.id = "iconeditor"; + ie.innerHTML = "
" + + "
" + + "
" + + this.CreateSelectBox("Typ", "icon", query, { "person": "Person" }, null, "iconeditor-type-") + "
" + + "
" + + this.CreateSelectBox("Organisation", "person-org", query, { "fw": "Feuerwehr", "thw": "Technisches Hilfswerk", "hilo": "Hilfsorganisationen, Bundeswehr", "fueh": "Einrichtungen der Führung", "pol": "Polizei, Bundespolizei, Zoll", "sonst": "Sonstige Einrichtungen der Gefahrenabwehr" }) + "
" + + this.CreateSelectBox("Funktion", "person-funct", query, { "sonder": "Sonder", "fueh": "Führung" }) + "
" + + this.CreateSelectBox("Rang", "person-rang", query, { "trupp": "Trupp", "grupp": "Gruppe", "zug": "Zug" }) + "
" + + "Text:
" + + this.CreateSelectBox("Typ", "person-typ", query, { "loesch": "Brandbekämpfung/Löscheinsatz", "sani": "Rettungswesen, Sanitätswesen, Gesundheitswesen", "betreu": "Betreuung" }, true) + "
" + + "
" + + "
" + + "
" + + "
"; + document.getElementsByTagName("body")[0].appendChild(ie); + }, + JoinObjectIntoQuery: function (queryobj) { + var query = new Array(); + for (var id in queryobj) { + if (Array.isArray(queryobj[id])) { + for (var i in queryobj[id]) { + query.push(encodeURIComponent(id) + "=" + encodeURIComponent(queryobj[id][i])); + } + } else { + query.push(encodeURIComponent(id) + "=" + encodeURIComponent(queryobj[id])); + } + } + return query.join("&"); + }, + ParseIcon: function (markerobj) { + var url = "../api/svg/person.svg"; + if (Object.prototype.hasOwnProperty.call(markerobj, "person")) { + url += "?icon=person"; + if (Object.prototype.hasOwnProperty.call(markerobj["person"], "org")) { + url += "&person-org=" + markerobj["person"]["org"]; + } + if (Object.prototype.hasOwnProperty.call(markerobj["person"], "funct")) { + url += "&person-funct=" + markerobj["person"]["funct"]; + } + if (Object.prototype.hasOwnProperty.call(markerobj["person"], "rang")) { + url += "&person-rang=" + markerobj["person"]["rang"]; + } + if (Object.prototype.hasOwnProperty.call(markerobj["person"], "text")) { + url += "&person-text=" + markerobj["person"]["text"]; + } + if (Object.prototype.hasOwnProperty.call(markerobj["person"], "typ") && Array.isArray(markerobj["person"]["typ"])) { + for (i in markerobj["person"]["typ"]) { + url += "&person-typ=" + markerobj["person"]["typ"][i]; + } + } + } + return ""; + }, + ParseJson: function (namesconfig) { + document.getElementById("content").innerHTML = ""; + var html = "
Namenseinträge in den Einstellungen
"; + html += ""; + html += ""; + html += ""; + for (var id in namesconfig) { + if (Object.prototype.hasOwnProperty.call(namesconfig, id)) { + var nameentry = namesconfig[id]; + html += "" + + "" + + ""; + if (Object.prototype.hasOwnProperty.call(nameentry, "marker.svg")) { + html += ""; + } else if (Object.prototype.hasOwnProperty.call(nameentry, "icon")) { + html += ""; + } else { + html += ""; + } + var gfilter = typeof nameentry.Group === "undefined" ? "no" : nameentry.Group; + html += ""; + html += "" + + ""; + } + } + html += ""; + html += ""; + html += "
IDNameIconFilter Gruppe
" + id + "" + nameentry["name"] + "" + this.ParseIcon(nameentry["marker.svg"]) + "" + this.filterGropus[gfilter] + "
"; + document.getElementById("content").innerHTML = html + "
"; + }, + Save: function () { + var rows = document.getElementById("nametable").children[1].children; + var namejson = {}; + for (var i = 0; i < rows.length; i++) { + if (rows[i].children[0].children.length === 1) { + alert("Bitte zuerst alle Zeilen speichern oder Löschen!"); + return; + } + var id = rows[i].children[0].innerText; + var name = rows[i].children[1].innerText; + namejson[id] = { "name": name, "Group": rows[i].children[3].attributes.rel.nodeValue }; + if (rows[i].children[2].children[0].hasAttribute("data")) { + namejson[id]["marker.svg"] = this.BuildIconJson(rows[i].children[2].children[0].data); + } + } + var savenames = new XMLHttpRequest(); + savenames.onreadystatechange = function () { + if (savenames.readyState === 4) { + if (savenames.status === 200) { + alert("Änderungen gespeichert!"); + } else if (savenames.status === 501) { + alert("Ein Fehler ist aufgetreten (invalid JSON)!"); + } + } + }; + savenames.open("PUT", "/admin/api/json/name", true); + savenames.send(JSON.stringify(namejson)); + }, + SaveIconEditor: function (id) { + var cell = document.getElementById(id); + cell.innerHTML = " "; + cell.removeAttribute("id"); + document.getElementById("iconeditor").remove(); + }, + SaveRow: function (el) { + var id = el.children[0].children[0].value; + var name = el.children[1].children[0].value; + var url = null; + var gfilter = el.children[3].children[0].selectedOptions[0].value; + if (gfilter === "---") { + gfilter = "no"; + } + if (el.children[2].children.length === 2) { + url = el.children[2].children[1].data; + } + el.innerHTML = "" + id + "" + + "" + name + ""; + if (url === null) { + el.innerHTML += ""; + } else { + el.innerHTML += ""; + } + el.innerHTML += "" + this.filterGropus[gfilter] + ""; + el.innerHTML += " "; + }, + SplitQueryIntoObject: function (query) { + if (query.indexOf("?") !== -1) { + query = query.split("?")[1]; + } + var queryobj = {}; + var pairs = query.split("&"); + for (var i = 0; i < pairs.length; i++) { + var pair = pairs[i].split("="); + if (Object.prototype.hasOwnProperty.call(queryobj, decodeURIComponent(pair[0]))) { + if (Array.isArray(queryobj[decodeURIComponent(pair[0])])) { + queryobj[decodeURIComponent(pair[0])].push(decodeURIComponent(pair[1] || "")); + } else { + var tmp = queryobj[decodeURIComponent(pair[0])]; + queryobj[decodeURIComponent(pair[0])] = new Array(); + queryobj[decodeURIComponent(pair[0])].push(tmp); + queryobj[decodeURIComponent(pair[0])].push(decodeURIComponent(pair[1] || "")); + } + } else { + queryobj[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || ""); + } + } + return queryobj; + }, + SplitUrlIntoParts: function (url) { + var parts = url.split("?"); + return { "file": parts[0], "query": parts[1] || "" }; + } +}; \ No newline at end of file diff --git a/Lora-Map/resources/admin/js/settings.js b/Lora-Map/resources/admin/js/settings.js new file mode 100644 index 0000000..def9417 --- /dev/null +++ b/Lora-Map/resources/admin/js/settings.js @@ -0,0 +1,330 @@ +var Settings = { + //public functions + Abort: function (el) { + el.parentNode.removeChild(el); + }, + AddDensity: function () { + var newrow = document.createElement("tr"); + newrow.innerHTML = ""; + newrow.innerHTML += ""; + newrow.innerHTML += ""; + newrow.innerHTML += ""; + newrow.innerHTML += " "; + document.getElementById("crowdtable").children[1].appendChild(newrow); + }, + AddFight: function () { + var newrow = document.createElement("tr"); + newrow.innerHTML = ""; + newrow.innerHTML += ""; + newrow.innerHTML += ""; + newrow.innerHTML += ""; + newrow.innerHTML += " "; + document.getElementById("fighttable").children[1].appendChild(newrow); + }, + AddSensor: function () { + var newrow = document.createElement("tr"); + newrow.innerHTML = ""; + newrow.innerHTML += ""; + newrow.innerHTML += ""; + newrow.innerHTML += ""; + newrow.innerHTML += " "; + document.getElementById("sensortable").children[1].appendChild(newrow); + }, + Delete: function (el) { + var answ = window.prompt("Wollen sie den Eintrag für \"" + el.firstChild.innerHTML + "\" wirklich löschen?", ""); + if (answ !== null) { + el.parentNode.removeChild(el); + } + }, + EditDensity: function (el) { + el.innerHTML = "" + + "" + + "" + + "" + + " "; + }, + EditFight: function (el) { + el.innerHTML = "" + + "" + + "" + + "" + + " "; + }, + EditSensor: function (el) { + el.innerHTML = "" + + "" + + "" + + "" + + " "; + }, + ParseJson: function (jsonsettings) { + if (typeof jsonsettings.StartPos === "undefined") { + jsonsettings.StartPos = { lat: 0, lon: 0 }; + } + if (typeof jsonsettings.CellIds === "undefined") { + jsonsettings.CellIds = []; + } + if (typeof jsonsettings.GridRadius === "undefined") { + jsonsettings.GridRadius = 1000; + } + if (typeof jsonsettings.FightDedection === "undefined") { + jsonsettings.FightDedection = []; + } + if (typeof jsonsettings.CrwodDensity === "undefined") { + jsonsettings.CrwodDensity = []; + } + if (typeof jsonsettings.Counting === "undefined") { + jsonsettings.Counting = []; + } + if (typeof jsonsettings.Sensors === "undefined") { + jsonsettings.Sensors = []; + } + var html = "
Einstellungen
"; + html += "
Startpunkt: Lat, Lon
"; + html += "
CellId's für DWD-Wetterwarnungen: (Trennen durch \";\", cap_warncellids_csv)
"; + html += "
Radius für das Grid um den Startpunkt: m
"; + html += "
Fight Dedection Kameras:
" + this._renderFightDedection(jsonsettings.FightDedection) + "
"; + html += "
Crowd Density Kameras:
" + this._renderCrowdDensity(jsonsettings.CrwodDensity) + "
"; + html += "
Sensors:
" + this._renderSensorSettings(jsonsettings.Sensors) + "
"; + html += "
"; + document.getElementById("content").innerHTML = html + "
"; + }, + Save: function () { + var ret = {}; + ret.StartPos = {}; + ret.StartPos.lat = parseFloat(document.getElementById("startlat").value.replace(",", ".")); + ret.StartPos.lon = parseFloat(document.getElementById("startlon").value.replace(",", ".")); + ret.CellIds = document.getElementById("wetterids").value.split(";"); + ret.GridRadius = parseInt(document.getElementById("gridrad").value); + + var rowsf = document.getElementById("fighttable").children[1].children; + var fightjson = {}; + for (var i = 0; i < rowsf.length; i++) { + if (rowsf[i].children[0].children.length === 1) { + alert("Bitte zuerst alle Zeilen speichern oder Löschen!"); + return; + } + var id = rowsf[i].children[0].innerText; + var coords = rowsf[i].children[1].innerHTML.split("
"); + var polyjson = []; + for (var j = 0; j < coords.length; j++) { + var coord = coords[j].split(";"); + polyjson[j] = { "Lat": this._filterFloat(coord[0]), "Lon": this._filterFloat(coord[1]) }; + } + fightjson[id] = { "Poly": polyjson, "Alias": rowsf[i].children[2].innerText, "Level": this._filterFloat(rowsf[i].children[3].innerText) }; + } + ret.FightDedection = fightjson; + + var rowsc = document.getElementById("crowdtable").children[1].children; + var crowdjson = {}; + for (i = 0; i < rowsc.length; i++) { + if (rowsc[i].children[0].children.length === 1) { + alert("Bitte zuerst alle Zeilen speichern oder Löschen!"); + return; + } + id = rowsc[i].children[0].innerText; + var num = this._filterFloat(rowsc[i].children[1].innerText); + coords = rowsc[i].children[2].innerHTML.split("
"); + + polyjson = []; + for (j = 0; j < coords.length; j++) { + coord = coords[j].split(";"); + polyjson[j] = { "Lat": this._filterFloat(coord[0]), "Lon": this._filterFloat(coord[1]) }; + } + crowdjson[id] = { + "Poly": polyjson, + "Count": num, + "Alias": rowsc[i].children[3].innerText + }; + } + ret.CrwodDensity = crowdjson; + + var rowss = document.getElementById("sensortable").children[1].children; + var sensorjson = {}; + for (i = 0; i < rowss.length; i++) { + if (rowss[i].children[0].children.length === 1) { + alert("Bitte zuerst alle Zeilen speichern oder Löschen!"); + return; + } + id = rowss[i].children[0].innerText; + coord = rowss[i].children[2].innerHTML.split(";"); + sensorjson[id] = { + "Poly": { + "Lat": this._filterFloat(coord[0]), + "Lon": this._filterFloat(coord[1]) + }, + "Level": this._filterFloat(rowss[i].children[3].innerText), + "Alias": rowss[i].children[1].innerText + }; + } + ret.Sensors = sensorjson; + + var savesettings = new XMLHttpRequest(); + savesettings.onreadystatechange = function () { + if (savesettings.readyState === 4) { + if (savesettings.status === 200) { + alert("Änderungen gespeichert!"); + } else if (savesettings.status === 501) { + alert("Ein Fehler ist aufgetreten (invalid JSON)!"); + } + } + }; + savesettings.open("PUT", "/admin/api/json/setting", true); + savesettings.send(JSON.stringify(ret)); + }, + SaveRowdensity: function (el) { + var coords = el.children[2].children[0].value.replace(/\n/gi, "
"); + var coordscheck = coords.split("
"); + var fail = false; + for (var i = 0; i < coordscheck.length; i++) { + var coord = coordscheck[i].split(";"); + if (coord.length !== 2) { + fail = true; + break; + } + if (isNaN(this._filterFloat(coord[0])) || isNaN(this._filterFloat(coord[1]))) { + fail = true; + break; + } + } + if (fail) { + alert("Die Eingabe der Koordinaten ist nicht Korrekt!\n\nBeispiel:\n50.7;7.8\n50.6;7.9"); + return; + } + if (isNaN(this._filterFloat(el.children[1].children[0].value))) { + alert("Die Eingabe der Maximalen Anzahl der Personen ist nicht Korrekt, erwarte eine Zahl."); + return; + } + el.innerHTML = "" + el.children[0].children[0].value + "" + + "" + el.children[1].children[0].value + "" + + "" + coords + "" + + "" + el.children[3].children[0].value + "" + + " "; + }, + SaveRowfight: function (el) { + var coords = el.children[1].children[0].value.replace(/\n/gi, "
"); + var coordscheck = coords.split("
"); + var fail = false; + for (var i = 0; i < coordscheck.length; i++) { + var coord = coordscheck[i].split(";"); + if (coord.length !== 2) { + fail = true; + break; + } + if (isNaN(this._filterFloat(coord[0])) || isNaN(this._filterFloat(coord[1]))) { + fail = true; + break; + } + } + if (isNaN(this._filterFloat(el.children[3].children[0].value))) { + alert("Die Eingabe des Alertlevel erwartet einen Float"); + return; + } + if (fail) { + alert("Die Eingabe der Koordinaten ist nicht Korrekt!\n\nBeispiel:\n50.7;7.8\n50.6;7.9"); + return; + } + el.innerHTML = "" + el.children[0].children[0].value + "" + + "" + coords + "" + + "" + el.children[2].children[0].value + "" + + "" + this._filterFloat(el.children[3].children[0].value) + "" + + " "; + }, + SaveRowSensor: function (el) { + var coords = el.children[2].children[0].value; + var coord = coords.split(";"); + var fail = false; + if (coord.length !== 2) { + fail = true; + } else if (isNaN(this._filterFloat(coord[0])) || isNaN(this._filterFloat(coord[1]))) { + fail = true; + } + if (isNaN(this._filterFloat(el.children[3].children[0].value))) { + alert("Die Eingabe des Alertlevel erwartet einen Float"); + return; + } + if (fail) { + alert("Die Eingabe der Koordinaten ist nicht Korrekt!\n\nBeispiel:\n50.7;7.8"); + return; + } + el.innerHTML = "" + el.children[0].children[0].value + "" + + "" + el.children[1].children[0].value + "" + + "" + coords + "" + + "" + this._filterFloat(el.children[3].children[0].value) + "" + + " "; + }, + //private functions + _filterFloat: function (value) { + if (/^(-|\+)?([0-9]+(\.[0-9]+)?|Infinity)$/.test(value)) { + return Number(value); + } + return NaN; + }, + _renderCrowdDensity: function (json) { + var ret = ""; + ret += ""; + ret += ""; + ret += ""; + for (var id in json) { + var coords = []; + for (var i = 0; i < json[id].Poly.length; i++) { + coords[i] = json[id].Poly[i].Lat + ";" + json[id].Poly[i].Lon; + } + ret += "" + + "" + + "" + + "" + + "" + + "" + + ""; + } + ret += ""; + ret += ""; + ret += "
IDPersonenanzahlKoordinatenAlias
" + id + "" + json[id].Count + "" + coords.join("
") + "
" + json[id].Alias + "
"; + return ret; + }, + _renderFightDedection: function (json) { + var ret = ""; + ret += ""; + ret += ""; + ret += ""; + for (var id in json) { + var coords = []; + for (var i = 0; i < json[id].Poly.length; i++) { + coords[i] = json[id].Poly[i].Lat + ";" + json[id].Poly[i].Lon; + } + ret += "" + + "" + + "" + + "" + + "" + + "" + + ""; + } + ret += ""; + ret += ""; + ret += "
IDKoordinatenAliasAlertlimit
" + id + "" + coords.join("
") + "
" + json[id].Alias + "" + json[id].Level + "
"; + return ret; + }, + _renderSensorSettings: function (json) { + var ret = ""; + ret += ""; + ret += ""; + + ret += ""; + for (var id in json) { + ret += "" + + "" + + "" + + "" + + "" + + "" + + ""; + } + ret += ""; + + ret += ""; + ret += "
IDAliasKoordinatenWarn above
" + id + "" + json[id].Alias + "" + json[id].Poly.Lat + ";" + json[id].Poly.Lon + "" + json[id].Level + "
"; + return ret; + }, +}; \ No newline at end of file diff --git a/Lora-Map/resources/css/global.css b/Lora-Map/resources/css/global.css index 09f193e..7f30609 100644 --- a/Lora-Map/resources/css/global.css +++ b/Lora-Map/resources/css/global.css @@ -141,7 +141,7 @@ object { } #pannels #pannels_pos .item .icon img { height: 40px; - width: 40px; + width: 35px; margin-left: 3px; } #pannels #pannels_pos .item .line1 .name { diff --git a/Lora-Map/resources/js/functions.js b/Lora-Map/resources/js/functions.js index 61c211d..791b303 100644 --- a/Lora-Map/resources/js/functions.js +++ b/Lora-Map/resources/js/functions.js @@ -1,62 +1,15 @@ var FunctionsObject = { + /// private variables _internalTimeOffset: 0, + /// public functions Start: function () { - setInterval(this._Runner60000, 60000); - setInterval(this._Runner1000, 1000); - this._Runner60000(); - this._Runner1000(); - this._RunnerOnce(); + setInterval(this._QueryJsonEveryMinute, 60000); + setInterval(this._QueryJsonEverySecond, 1000); + this._QueryJsonEveryMinute(); + this._QueryJsonEverySecond(); + this._QueryJsonStartup(); return this; }, - _Runner60000: function () { - var get60000 = new XMLHttpRequest(); - get60000.onreadystatechange = function () { - if (get60000.readyState === 4 && get60000.status === 200) { - var json = JSON.parse(get60000.responseText); - FunctionsObject._ParseAJAX(json["currenttime"]); - } - }; - get60000.open("GET", "/get60000", true); - get60000.send(); - }, - _Runner1000: function () { - var get1000 = new XMLHttpRequest(); - get1000.onreadystatechange = function () { - if (get1000.readyState === 4 && get1000.status === 200) { - var json = JSON.parse(get1000.responseText); - MarkerObject._ParseAJAXLoc(json["loc"]); - MarkerObject._ParseAJAXPanic(json["panic"]); - OverlayObject._ParseAJAXCount(json["cameracount"]); - OverlayObject._ParseAJAXDensity(json["crowdcount"]); - MarkerObject._ParseAJAXSensors(json["sensors"]); - MenuObject._ParseAJAXWeatherAlerts(json["weatherwarnings"]); - MapObject._ParseAJAXFightDedection(json["fightdedect"]); - MapObject._ParseAJAXDensity(json["crowdcount"]); - } - }; - get1000.open("GET", "/get1000", true); - get1000.send(); - }, - _RunnerOnce: function () { - var getonce = new XMLHttpRequest(); - getonce.onreadystatechange = function () { - if (getonce.readyState === 4 && getonce.status === 200) { - var json = JSON.parse(getonce.responseText); - MapObject._ParseAJAXLayers(json["getlayer"]); - MapObject._ParseAJAXGeo(json["getgeo"]); - MapObject._ParseAJAXSettings(json["startup"]); - OverlayObject._ParseAJAXSettings(json["startup"]); - MarkerObject._ParseAJAXSettings(json["startup"]); - } - }; - getonce.open("GET", "/getonce", true); - getonce.send(); - }, - _ParseAJAX: function (utcobject) { - if (utcobject.hasOwnProperty("utc")) { - this._internalTimeOffset = Date.now() - Date.parse(utcobject["utc"]); - } - }, TimeCalculation: function (timestr, type) { if (type === "diffraw" || type === "difftext" || type === "difftextn") { var diff = Math.round((Date.now() - Date.parse(timestr) - this._internalTimeOffset) / 1000); @@ -86,5 +39,55 @@ var str = date.toLocaleString(); return str; } + }, + /// private functions + _ParseAJAX: function (utcobject) { + if (Object.prototype.hasOwnProperty.call(utcobject, "utc")) { + this._internalTimeOffset = Date.now() - Date.parse(utcobject["utc"]); + } + }, + _QueryJsonEveryMinute: function () { + var get60000 = new XMLHttpRequest(); + get60000.onreadystatechange = function () { + if (get60000.readyState === 4 && get60000.status === 200) { + var json = JSON.parse(get60000.responseText); + FunctionsObject._ParseAJAX(json); + } + }; + get60000.open("GET", "/api/time", true); + get60000.send(); + }, + _QueryJsonEverySecond: function () { + var get1000 = new XMLHttpRequest(); + get1000.onreadystatechange = function () { + if (get1000.readyState === 4 && get1000.status === 200) { + var json = JSON.parse(get1000.responseText); + MarkerObject.ParseAJAXPositionModel(json.position); + MarkerObject.ParseAJAXSensorModel(json.sensor); + + OverlayObject.ParseAJAXCameraModel(json.camera); + + MapObject.ParseAJAXCameraModel(json.camera); + + MenuObject.ParseAJAXSensorModel(json.sensor); + } + }; + get1000.open("GET", "/api/json/position,camera,sensor", true); + get1000.send(); + }, + _QueryJsonStartup: function () { + var getonce = new XMLHttpRequest(); + getonce.onreadystatechange = function () { + if (getonce.readyState === 4 && getonce.status === 200) { + var json = JSON.parse(getonce.responseText); + MarkerObject.ParseAJAXSettings(json.settings); + + OverlayObject.ParseAJAXSettings(json.settings); + + MapObject.ParseAJAXSettings(json.settings); + } + }; + getonce.open("GET", "/api/json/settings", true); + getonce.send(); } }.Start(); \ No newline at end of file diff --git a/Lora-Map/resources/js/map.js b/Lora-Map/resources/js/map.js index 1592afb..dff944f 100644 --- a/Lora-Map/resources/js/map.js +++ b/Lora-Map/resources/js/map.js @@ -1,20 +1,155 @@ var MapObject = { - Map: {}, + /// public variables GeoJson: {}, - _FightDedection: {}, + Map: {}, + /// private variables _DensityAreas: {}, + _FightDedection: {}, _SpecialMarkers: new Array(), + /// public functions + JumpTo: function (lat, lon) { + this.Map.flyTo([lat, lon], 19); + }, + ParseAJAXCameraModel: function (json) { + this._ParseAJAXFightDedection(json.Fights); + this._ParseAJAXDensity(json.Density); + }, + ParseAJAXSettings: function (settings) { + this._ParseAJAXLayers(settings.Layers); + this._ParseAJAXGeo(settings.GeoLayer); + this.Map.panTo([settings.Startloclat, settings.Startloclon]); + this._GenerateGrid(settings.Grid); + this._GenerateFightBoxes(settings.FightDedection); + this._GenerateDensityBoxes(settings.DensityArea); + }, Start: function () { this.Map = L.map('bigmap').setView([0, 0], 16); this._SetupMapZoomFontsize(); this._SetupClickHandler(); return this; }, - _ParseAJAXSettings: function (settings) { - this.Map.panTo([settings.Startloclat, settings.Startloclon]); - this._GenerateGrid(settings.Grid); - this._GenerateFightBoxes(settings.FightDedection); - this._GenerateDensityBoxes(settings.DensityArea); + /// private functions + _createRGB: function (current, max) { + return "hsl(" + 120 * (1 - current / max) + ",100%,50%)"; + }, + _GenerateDensityBoxes: function (densityareas) { + for (var cameraid in densityareas) { + this._DensityAreas[cameraid] = { 'Poly': L.polygon(densityareas[cameraid].Polygon, { color: 'hsl(120,100%,50%)', weight: 1 }).addTo(this.Map), 'Maximum': densityareas[cameraid].Maximum }; + this._DensityAreas[cameraid].Poly.bindPopup("Besuchermenge:
" + + "Besucher (0/" + this._DensityAreas[cameraid].Maximum + ") Personen
" + + ""); + } + }, + _GenerateFightBoxes: function (fightdedection) { + for (var cameraid in fightdedection) { + this._FightDedection[cameraid] = {}; + this._FightDedection[cameraid].Box = L.polygon(fightdedection[cameraid].Polygon, { color: 'black', weight: 1 }).addTo(this.Map); + this._FightDedection[cameraid].Box.bindPopup("Fightdedection " + fightdedection[cameraid].Alias); + this._FightDedection[cameraid].Level = fightdedection[cameraid].Level; + } + }, + _GenerateGrid: function (grid) { + for (var i = 0; i < grid.Major.length; i++) { + var linemajor = grid.Major[i]; + L.polyline([[linemajor.from[0], linemajor.from[1]], [linemajor.to[0], linemajor.to[1]]], { color: "red", weight: 1, interactive: false }).addTo(this.Map); + } + for (var j = 0; j < grid.Minor.length; j++) { + var lineminor = grid.Minor[j]; + L.polyline([[lineminor.from[0], lineminor.from[1]], [lineminor.to[0], lineminor.to[1]]], { color: "red", weight: 0.7, opacity: 0.5, interactive: false }).addTo(this.Map); + } + }, + _HidePanel: function (e) { + MenuObject.ShowHidePanel(null); + }, + _ParseAJAXDensity: function (json) { + for (var cameraid in json) { + if (Object.prototype.hasOwnProperty.call(this._DensityAreas, cameraid)) { + var crowd = json[cameraid]; + var box = this._DensityAreas[cameraid].Poly; + var max = this._DensityAreas[cameraid].Maximum; + var cur = crowd.DensityCount; + if (cur > max) { + cur = max; + } + box.setStyle({ color: this._createRGB(cur, max) }); + var p = box.getPopup().setContent("Besuchermenge:
" + + "Besucher (" + crowd.DensityCount + "/" + max + ") Personen
" + + "").update(); + } + } + }, + _ParseAJAXFightDedection: function (json) { + for (var cameraid in json) { + if (Object.prototype.hasOwnProperty.call(this._FightDedection, cameraid)) { + var fight = json[cameraid]; + var box = this._FightDedection[cameraid].Box; + var diff = FunctionsObject.TimeCalculation(fight["LastUpdate"], "diffraw"); + if (fight["FightProbability"] > this._FightDedection[cameraid].Level) { + if (diff <= 10 && box.options.color === "black") { + box.setStyle({ color: 'rgb(' + fight["FightProbability"] * 255 + ',0,0)' }); + } else if (diff <= 10 && box.options.color !== "black") { + if (diff % 2 === 0) { + box.setStyle({ color: 'rgb(' + fight["FightProbability"] * 255 + ',0,0)' }); + } else { + box.setStyle({ color: 'green' }); + } + } else if (diff > 10 && box.options.color !== "black") { + box.setStyle({ color: 'black' }); + } + } + } + } + }, + _ParseAJAXGeo: function (geo) { + if (!(Object.keys(geo).length === 0 && geo.constructor === Object)) { + this.GeoJson = geo; + L.geoJSON(geo, { + style: function (features) { + return { + color: typeof features.properties["stroke"] === "undefined" ? '#000000' : features.properties["stroke"], + weight: typeof features.properties["stroke-width"] === "undefined" ? 1 : features.properties["stroke-width"], + opacity: typeof features.properties["stroke-opacity"] === "undefined" ? 1 : features.properties["stroke-opacity"], + fillColor: typeof features.properties["fill"] === "undefined" ? '#ffffff' : features.properties["fill"], + fillOpacity: typeof features.properties["fill-opacity"] === "undefined" ? 1 : features.properties["fill-opacity"] + }; + }, + onEachFeature: function (feature, layer) { + if (feature.geometry.type === "Polygon" || feature.geometry.type === "Point" && Object.prototype.hasOwnProperty.call(feature.properties, "icon")) { + var text = "" + feature.properties.name + ""; + if (Object.prototype.hasOwnProperty.call(feature.properties, "description")) { + text = text + "
" + feature.properties.description; + } + layer.bindPopup(text, { maxWidth: 485 }); + } + }, + pointToLayer: function (geoJsonPoint, latlng) { + if (Object.prototype.hasOwnProperty.call(geoJsonPoint.properties, "description") && geoJsonPoint.properties["description"] === "snumber" && !Object.prototype.hasOwnProperty.call(geoJsonPoint.properties, "icon")) { + var snumbericon = L.marker(latlng, { + icon: new L.DivIcon({ + className: "snumber-icon", + html: geoJsonPoint.properties["name"], + iconSize: [8, 8] + }), + interactive: false + }); + MapObject._SpecialMarkers.push(snumbericon); + return snumbericon; + } else if (Object.prototype.hasOwnProperty.call(geoJsonPoint.properties, "description") && geoJsonPoint.properties["description"] === "coord" && !Object.prototype.hasOwnProperty.call(geoJsonPoint.properties, "icon")) { + var coordicon = L.marker(latlng, { + icon: new L.DivIcon({ + className: "coord-icon", + html: geoJsonPoint.properties["name"] + }), + interactive: false + }); + MapObject._SpecialMarkers.push(coordicon); + return coordicon; + } else if (Object.prototype.hasOwnProperty.call(geoJsonPoint.properties, "icon")) { + return L.marker(latlng, { icon: L.icon({ iconUrl: "css/icons/cctv.png", iconSize: [32, 32] }) }); + } + } + }).addTo(this.Map); + } }, _ParseAJAXLayers: function (maps) { var i = 0; @@ -43,7 +178,7 @@ } } for (key in maps) { - if (!baseMaps.hasOwnProperty(maps[key]["title"])) { + if (!Object.prototype.hasOwnProperty.call(baseMaps, maps[key]["title"])) { baseMaps[maps[key]["title"]] = L.tileLayer(maps[key]["url"], { attribution: maps[key]["attribution"], minZoom: maps[key]["minZoom"], @@ -55,124 +190,8 @@ L.control.layers(baseMaps).addTo(this.Map); } }, - _GenerateGrid: function (grid) { - for (var i = 0; i < grid.Major.length; i++) { - var linemajor = grid.Major[i]; - L.polyline([[linemajor.from[0], linemajor.from[1]], [linemajor.to[0], linemajor.to[1]]], { color: "red", weight: 1, interactive: false }).addTo(this.Map); - } - for (var j = 0; j < grid.Minor.length; j++) { - var lineminor = grid.Minor[j]; - L.polyline([[lineminor.from[0], lineminor.from[1]], [lineminor.to[0], lineminor.to[1]]], { color: "red", weight: 0.7, opacity: 0.5, interactive: false }).addTo(this.Map); - } - }, - _GenerateFightBoxes: function (fightdedection) { - for (var cameraid in fightdedection) { - this._FightDedection[cameraid] = {}; - this._FightDedection[cameraid].Box = L.polygon(fightdedection[cameraid].Polygon, { color: 'black', weight: 1 }).addTo(this.Map); - this._FightDedection[cameraid].Box.bindPopup("Fightdedection " + fightdedection[cameraid].Alias); - this._FightDedection[cameraid].Level = fightdedection[cameraid].Level; - } - }, - _ParseAJAXFightDedection: function (json) { - for (var cameraid in json) { - if (this._FightDedection.hasOwnProperty(cameraid)) { - var fight = json[cameraid]; - var box = this._FightDedection[cameraid].Box; - var diff = FunctionsObject.TimeCalculation(fight["LastUpdate"], "diffraw"); - if (fight["FightProbability"] > this._FightDedection[cameraid].Level) { - if (diff <= 10 && box.options.color === "black") { - box.setStyle({ color: 'rgb(' + fight["FightProbability"] * 255 + ',0,0)' }); - } else if (diff <= 10 && box.options.color !== "black") { - if (diff % 2 === 0) { - box.setStyle({ color: 'rgb(' + fight["FightProbability"] * 255 + ',0,0)' }); - } else { - box.setStyle({ color: 'green' }); - } - } else if (diff > 10 && box.options.color !== "black") { - box.setStyle({ color: 'black' }); - } - } - } - } - }, - _GenerateDensityBoxes: function (densityareas) { - for (var cameraid in densityareas) { - this._DensityAreas[cameraid] = { 'Poly': L.polygon(densityareas[cameraid].Polygon, { color: 'hsl(120,100%,50%)', weight: 1 }).addTo(this.Map), 'Maximum': densityareas[cameraid].Maximum }; - this._DensityAreas[cameraid].Poly.bindPopup("Besuchermenge:
" + - "Besucher (0/" + this._DensityAreas[cameraid].Maximum + ") Personen
" + - ""); - } - }, - _ParseAJAXDensity: function (json) { - for (var cameraid in json) { - if (this._DensityAreas.hasOwnProperty(cameraid)) { - var crowd = json[cameraid]; - var box = this._DensityAreas[cameraid].Poly; - var max = this._DensityAreas[cameraid].Maximum; - var cur = crowd.DensityCount; - if (cur > max) { - cur = max; - } - box.setStyle({ color: this._createRGB(cur, max) }); - var p = box.getPopup().setContent("Besuchermenge:
" + - "Besucher (" + crowd.DensityCount + "/" + max + ") Personen
" + - "").update(); - } - } - }, - _createRGB: function (current, max) { - return "hsl(" + 120 * (1 - current / max) + ",100%,50%)"; - }, - _ParseAJAXGeo: function (geo) { - if (!(Object.keys(geo).length === 0 && geo.constructor === Object)) { - this.GeoJson = geo; - L.geoJSON(geo, { - style: function (features) { - return { - color: typeof features.properties["stroke"] === "undefined" ? '#000000' : features.properties["stroke"], - weight: typeof features.properties["stroke-width"] === "undefined" ? 1 : features.properties["stroke-width"], - opacity: typeof features.properties["stroke-opacity"] === "undefined" ? 1 : features.properties["stroke-opacity"], - fillColor: typeof features.properties["fill"] === "undefined" ? '#ffffff' : features.properties["fill"], - fillOpacity: typeof features.properties["fill-opacity"] === "undefined" ? 1 : features.properties["fill-opacity"] - }; - }, - onEachFeature: function (feature, layer) { - if (feature.geometry.type === "Polygon" || feature.geometry.type === "Point" && feature.properties.hasOwnProperty("icon")) { - var text = "" + feature.properties.name + ""; - if (feature.properties.hasOwnProperty("description")) { - text = text + "
" + feature.properties.description; - } - layer.bindPopup(text, { maxWidth: 485 }); - } - }, - pointToLayer: function (geoJsonPoint, latlng) { - if (geoJsonPoint.properties.hasOwnProperty("description") && geoJsonPoint.properties["description"] === "snumber" && !geoJsonPoint.properties.hasOwnProperty("icon")) { - var snumbericon = L.marker(latlng, { - icon: new L.DivIcon({ - className: "snumber-icon", - html: geoJsonPoint.properties["name"], - iconSize: [8, 8] - }), - interactive: false - }); - MapObject._SpecialMarkers.push(snumbericon); - return snumbericon; - } else if (geoJsonPoint.properties.hasOwnProperty("description") && geoJsonPoint.properties["description"] === "coord" && !geoJsonPoint.properties.hasOwnProperty("icon")) { - var coordicon = L.marker(latlng, { - icon: new L.DivIcon({ - className: "coord-icon", - html: geoJsonPoint.properties["name"] - }), - interactive: false - }); - MapObject._SpecialMarkers.push(coordicon); - return coordicon; - } else if (geoJsonPoint.properties.hasOwnProperty("icon")) { - return L.marker(latlng, { icon: L.icon({ iconUrl: "css/icons/cctv.png", iconSize: [32, 32] }) }); - } - } - }).addTo(this.Map); - } + _SetupClickHandler: function () { + this.Map.on("click", this._HidePanel); }, _SetupMapZoomFontsize: function () { this.Map.on('zoomend', function () { @@ -257,14 +276,5 @@ } MarkerObject.ScaleSensors("zoom"); }); - }, - _SetupClickHandler: function () { - this.Map.on("click", this._HidePanel); - }, - _HidePanel: function (e) { - MenuObject.ShowHidePanel(null); - }, - JumpTo: function (lat, lon) { - this.Map.flyTo([lat, lon], 19); } }.Start(); \ No newline at end of file diff --git a/Lora-Map/resources/js/marker.js b/Lora-Map/resources/js/marker.js index adc5c8d..8e8884a 100644 --- a/Lora-Map/resources/js/marker.js +++ b/Lora-Map/resources/js/marker.js @@ -1,20 +1,65 @@ var MarkerObject = { - _Markers: {}, - PanicData: {}, + /// public variables LocationData: {}, + PanicData: {}, VisibleMarkers: {}, + /// private variables + _Markers: {}, _Sensors: {}, _SensorSettings: {}, + /// public functions + ChangeFilter: function (select) { + this.VisibleMarkers = {}; + if (select.selectedOptions.length > 0) { + for (var i = 0; i < select.selectedOptions.length; i++) { + this.VisibleMarkers[select.selectedOptions[i].value] = true; + } + this.VisibleMarkers["no"] = true; + this.VisibleMarkers["___isset"] = true; + } + this._ParseAJAXLoc(this.LocationData); + }, + ParseAJAXPositionModel: function (json) { + this._ParseAJAXLoc(json.Positions); + this._ParseAJAXPanic(json.Alarms); + }, + ParseAJAXSensorModel: function (json) { + this._ParseAJAXSensors(json.Enviroments); + }, + ParseAJAXSettings: function (json) { + this._SensorSettings = json["Sensors"]; + }, + ScaleSensors: function (el) { + if (el === "zoom") { + for (var sensorid in this._Sensors) { + this.ScaleSensors(document.getElementById('MapSensor_id_' + sensorid)); + } + return; + } + var currentZoom = MapObject.Map.getZoom(); + var scale = 1; + if (currentZoom < 14) { + scale = 0; + } else if (currentZoom === 14) { + scale = 0.2; + } else if (currentZoom === 15) { + scale = 0.5; + } else if (currentZoom >= 16) { + scale = 1; + } + el.style.cssText = "transform: scale(" + scale + ");"; + }, Start: function () { return this; }, + /// private functions _ParseAJAXLoc: function (serverLocation) { this.LocationData = serverLocation; for (var key in this.LocationData) { - if (this.LocationData.hasOwnProperty(key)) { + if (Object.prototype.hasOwnProperty.call(this.LocationData, key)) { var positionItem = this.LocationData[key]; if (positionItem['Latitude'] !== 0 || positionItem['Longitude'] !== 0) { - if (!this._Markers.hasOwnProperty(key)) { + if (!Object.prototype.hasOwnProperty.call(this._Markers, key)) { var marker = null; if (positionItem['Icon'] === null) { marker = L.marker([positionItem['Latitude'], positionItem['Longitude']], { 'title': positionItem['Name'] }); @@ -51,7 +96,7 @@ } } } - if (positionItem.Group !== null && this.VisibleMarkers.hasOwnProperty("___isset") && !this.VisibleMarkers.hasOwnProperty(positionItem.Group)) { + if (positionItem.Group !== null && Object.prototype.hasOwnProperty.call(this.VisibleMarkers, "___isset") && !Object.prototype.hasOwnProperty.call(this.VisibleMarkers, positionItem.Group)) { this._Markers[key]._icon.style.opacity = 0; } else { var lasttime = FunctionsObject.TimeCalculation(positionItem['Recievedtime'], "diffraw"); @@ -76,11 +121,11 @@ _ParseAJAXPanic: function (serverPanic) { this.PanicData = serverPanic; for (var id in this.PanicData) { - if (this.PanicData.hasOwnProperty(id)) { + if (Object.prototype.hasOwnProperty.call(this.PanicData, id)) { var alertItem = this.PanicData[id]; - if (this._Markers.hasOwnProperty(id)) { + if (Object.prototype.hasOwnProperty.call(this._Markers, id)) { var marker = this._Markers[id]; - if (!(this.LocationData[id].Group !== null && this.VisibleMarkers.hasOwnProperty("___isset") && !this.VisibleMarkers.hasOwnProperty(this.LocationData[id].Group))) { + if (!(this.LocationData[id].Group !== null && Object.prototype.hasOwnProperty.call(this.VisibleMarkers, "___isset") /**/ && !Object.prototype.hasOwnProperty.call(this.VisibleMarkers, this.LocationData[id].Group))) { if (FunctionsObject.TimeCalculation(alertItem["Recievedtime"], "diffraw") <= 10 && marker._icon.className.indexOf(" marker-alert") === -1) { marker._icon.className += " marker-alert"; MenuObject.ShowMarkerInfoPerId(id); @@ -94,11 +139,11 @@ }, _ParseAJAXSensors: function (sensorjson) { for (var sensorid in sensorjson) { - if (sensorjson.hasOwnProperty(sensorid)) { - if (this._SensorSettings.hasOwnProperty(sensorid)) { + if (Object.prototype.hasOwnProperty.call(sensorjson, sensorid)) { + if (Object.prototype.hasOwnProperty.call(this._SensorSettings, sensorid)) { var sensordata = sensorjson[sensorid]; var sensorsettings = this._SensorSettings[sensorid]; - if (!this._Sensors.hasOwnProperty(sensorid)) { //Sensor is not drawn until now + if (!Object.prototype.hasOwnProperty.call(this._Sensors, sensorid)) { //Sensor is not drawn until now var sensor = null; var sensorIcon = L.divIcon({ className: 'sensoricon', @@ -122,39 +167,5 @@ } } } - }, - ScaleSensors: function (el) { - if (el === "zoom") { - for (var sensorid in this._Sensors) { - this.ScaleSensors(document.getElementById('MapSensor_id_' + sensorid)); - } - return; - } - var currentZoom = MapObject.Map.getZoom(); - var scale = 1; - if (currentZoom < 14) { - scale = 0; - } else if (currentZoom === 14) { - scale = 0.2; - } else if (currentZoom === 15) { - scale = 0.5; - } else if (currentZoom >= 16) { - scale = 1; - } - el.style.cssText = "transform: scale(" + scale + ");"; - }, - _ParseAJAXSettings: function(json) { - this._SensorSettings = json["Sensors"]; - }, - ChangeFilter: function (select) { - this.VisibleMarkers = {}; - if (select.selectedOptions.length > 0) { - for (var i = 0; i < select.selectedOptions.length; i++) { - this.VisibleMarkers[select.selectedOptions[i].value] = true; - } - this.VisibleMarkers["no"] = true; - this.VisibleMarkers["___isset"] = true; - } - this._ParseAJAXLoc(this.LocationData); } }.Start(); \ No newline at end of file diff --git a/Lora-Map/resources/js/menu.js b/Lora-Map/resources/js/menu.js index 5c2df10..763b7e3 100644 --- a/Lora-Map/resources/js/menu.js +++ b/Lora-Map/resources/js/menu.js @@ -1,9 +1,32 @@ var MenuObject = { + /// public variables statusToDevice: null, - _visiblePanel: null, + /// private variables _overviewStatus: new Array(), - Start: function () { - return this; + _visiblePanel: null, + /// public functions + ParseAJAXSensorModel: function (json) { + this._ParseAJAXWeatherAlerts(json.Weather.Warnungen); + }, + SearchInGeoJson: function (searchtext) { + var html = ""; + if (MapObject.GeoJson.features.length > 0) { + for (var i = 0; i < MapObject.GeoJson.features.length; i++) { + var feature = MapObject.GeoJson.features[i]; + if ((feature.properties.name.toLowerCase().indexOf(searchtext.toLowerCase()) !== -1 || + (typeof feature.properties.description !== "undefined" && feature.properties.description.toLowerCase().indexOf(searchtext.toLowerCase()) !== -1)) && + feature.geometry.type === "Polygon") { + if (feature.geometry.coordinates.length > 0 && feature.geometry.coordinates[0].length > 0 && feature.geometry.coordinates[0][0].length > 0) { + html += "
" + + "" + feature.properties.name + "" + + "" + (typeof feature.properties.description !== "undefined" ? feature.properties.description : "") + "" + + "" + + "
"; + } + } + } + } + document.getElementById("search_results").innerHTML = html; }, ShowHidePanel: function (name) { if (this._visiblePanel === null && name !== null) { @@ -32,15 +55,29 @@ this.statusToDevice = id; this.ShowHidePanel("pannels_info"); }, + Start: function () { + return this; + }, + SubmitLoginForm: function () { + var adminlogin = new XMLHttpRequest(); + adminlogin.onreadystatechange = function () { + if (adminlogin.readyState === 4 && adminlogin.status === 200) { + MenuObject._Update_pannels_admin(); + } + }; + adminlogin.open("POST", "/admin/login", true); + adminlogin.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + adminlogin.send("user=" + encodeURI(document.getElementById("pannels_admin_name").value) + "&pass=" + encodeURI(document.getElementById("pannels_admin_pass").value)); + }, UpdateStatus: function () { for (var id in MarkerObject.LocationData) { - if (MarkerObject.LocationData.hasOwnProperty(id)) { + if (Object.prototype.hasOwnProperty.call(MarkerObject.LocationData, id)) { var positionItem = MarkerObject.LocationData[id]; if (typeof this._overviewStatus[id] === "undefined") { this._overviewStatus[id] = this._CreateOverviewElement(positionItem, id); document.getElementById("pannels_pos").appendChild(this._overviewStatus[id]); } - if (positionItem.Group !== null && MarkerObject.VisibleMarkers.hasOwnProperty("___isset") && !MarkerObject.VisibleMarkers.hasOwnProperty(positionItem.Group)) { + if (positionItem.Group !== null && Object.prototype.hasOwnProperty.call(MarkerObject.VisibleMarkers, "___isset") && !Object.prototype.hasOwnProperty.call(MarkerObject.VisibleMarkers, positionItem.Group)) { if (this._overviewStatus[id].className.indexOf("filter") === -1) { this._overviewStatus[id].className = "item filter"; } @@ -51,8 +88,9 @@ } this._UpdateOverviewElement(positionItem, id); } - } + } }, + /// private functions _UpdateOverviewElement: function (positionItem, id) { if (positionItem["Batterysimple"] === 0) { document.getElementById("overview-color-id-" + id).style.backgroundColor = "red"; @@ -62,7 +100,9 @@ document.getElementById("overview-color-id-" + id).style.backgroundColor = "green"; } document.getElementById("overview-name-id-" + id).innerText = positionItem["Name"]; - document.getElementById("overview-akkuimg-id-" + id).src = "icons/akku/" + positionItem["Batterysimple"] + "-4.png"; + if (document.getElementById("overview-akkuimg-id-" + id).src.substring(document.getElementById("overview-akkuimg-id-" + id).src.indexOf("/", 7) + 1) !== "icons/akku/" + positionItem["Batterysimple"] + "-4.png") { + document.getElementById("overview-akkuimg-id-" + id).src = "icons/akku/" + positionItem["Batterysimple"] + "-4.png"; + } if (positionItem["Fix"]) { document.getElementById("overview-gps-id-" + id).innerText = "GPS-Empfang"; document.getElementById("overview-gps-id-" + id).style.color = "green"; @@ -78,11 +118,11 @@ } } else { if (document.getElementById("overview-icon-id-" + id).children[0].hasAttribute("src")) { - if (document.getElementById("overview-icon-id-" + id).children[0]["src"].substring(document.getElementById("overview-icon-id-" + id).children[0]["src"].indexOf("/", 7) + 1) !== positionItem['Icon'] + "&marker-bg=hidden") { - document.getElementById("overview-icon-id-" + id).children[0]["src"] = positionItem['Icon'] + "&marker-bg=hidden"; + if (document.getElementById("overview-icon-id-" + id).children[0]["src"].substring(document.getElementById("overview-icon-id-" + id).children[0]["src"].indexOf("/", 7) + 1) !== positionItem['MenuIcon']) { + document.getElementById("overview-icon-id-" + id).children[0]["src"] = positionItem['MenuIcon']; } } else { - document.getElementById("overview-icon-id-" + id).innerHTML = ""; + document.getElementById("overview-icon-id-" + id).innerHTML = ""; } } }, @@ -96,7 +136,7 @@ divItem.setAttribute("rel", id); divItem.innerHTML = ""; if (positionItem['Icon'] !== null) { - divItem.innerHTML += ""; + divItem.innerHTML += ""; } else { divItem.innerHTML += ""; } @@ -119,20 +159,9 @@ document.getElementById("pannels_admin").innerHTML = "Adminpannel"; } }, - SubmitLoginForm: function () { - var adminlogin = new XMLHttpRequest(); - adminlogin.onreadystatechange = function () { - if (adminlogin.readyState === 4 && adminlogin.status === 200) { - MenuObject._Update_pannels_admin(); - } - }; - adminlogin.open("POST", "/admin/login", true); - adminlogin.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); - adminlogin.send("user=" + encodeURI(document.getElementById("pannels_admin_name").value) + "&pass=" + encodeURI(document.getElementById("pannels_admin_pass").value)); - }, _Update_pannels_info: function () { document.getElementById("pannels_info").innerHTML = ""; - if (MarkerObject.LocationData.hasOwnProperty(this.statusToDevice)) { + if (Object.prototype.hasOwnProperty.call(MarkerObject.LocationData, this.statusToDevice)) { var positionItem = MarkerObject.LocationData[this.statusToDevice]; var html = "
Name: " + positionItem["Name"] + "
"; html += "
Batterie: " + positionItem["Battery"] + "V
"; @@ -148,7 +177,7 @@ html += "
Letzter Wert: Vor: " + FunctionsObject.TimeCalculation(positionItem["Lastgpspostime"], "difftext") + "
"; html += "
Update: " + FunctionsObject.TimeCalculation(positionItem["Recievedtime"], "str") + "
Vor: " + FunctionsObject.TimeCalculation(positionItem["Recievedtime"], "difftext") + "
"; html += "
RSSI: " + positionItem["Rssi"] + ", SNR: " + positionItem["Snr"] + "
"; - if (MarkerObject.PanicData.hasOwnProperty(this.statusToDevice)) { + if (Object.prototype.hasOwnProperty.call(MarkerObject.PanicData, this.statusToDevice)) { var panicData = MarkerObject.PanicData[this.statusToDevice]; if (panicData["ButtonPressed"].length > 0) { html += "
Alerts:"; @@ -186,7 +215,7 @@ if (FunctionsObject.TimeCalculation(walert.From, "diffraw") < 0) { html += "in " + FunctionsObject.TimeCalculation(walert.From, "difftextn"); } else { - html += "vor " + FunctionsObject.TimeCalculation(walert.From, "difftext"); + html += "seit " + FunctionsObject.TimeCalculation(walert.From, "difftext"); } html += " Bis: in " + FunctionsObject.TimeCalculation(walert.To, "difftextn") + "" + "
"; @@ -197,25 +226,5 @@ document.getElementById("pannels_weather").innerHTML = "

Keine Gefahren

"; document.getElementById("menucol_weather_icon").className = "weather"; } - }, - SearchInGeoJson: function (searchtext) { - var html = ""; - if (MapObject.GeoJson.features.length > 0) { - for (var i = 0; i < MapObject.GeoJson.features.length; i++) { - var feature = MapObject.GeoJson.features[i]; - if ((feature.properties.name.toLowerCase().indexOf(searchtext.toLowerCase()) !== -1 || - (typeof feature.properties.description !== "undefined" && feature.properties.description.toLowerCase().indexOf(searchtext.toLowerCase()) !== -1)) && - feature.geometry.type === "Polygon") { - if (feature.geometry.coordinates.length > 0 && feature.geometry.coordinates[0].length > 0 && feature.geometry.coordinates[0][0].length > 0) { - html += "
" + - "" + feature.properties.name + "" + - "" + (typeof feature.properties.description !== "undefined" ? feature.properties.description : "") + "" + - "" + - "
"; - } - } - } - } - document.getElementById("search_results").innerHTML = html; } }.Start(); \ No newline at end of file diff --git a/Lora-Map/resources/js/overlays.js b/Lora-Map/resources/js/overlays.js index 34ae1fe..4c85cf3 100644 --- a/Lora-Map/resources/js/overlays.js +++ b/Lora-Map/resources/js/overlays.js @@ -1,12 +1,22 @@ var OverlayObject = { + /// private variables _DensitySettings: {}, + /// public functions + ParseAJAXCameraModel: function (json) { + this._ParseAJAXCount(json.Counter); + this._ParseAJAXDensity(json.Density); + }, + ParseAJAXSettings: function (json) { + this._DensitySettings = json["DensityArea"]; + }, Start: function () { return this; }, + /// private functions _ParseAJAXCount: function (cameracounts) { var camerastext = ""; for (var cameraid in cameracounts) { - if (cameracounts.hasOwnProperty(cameraid)) { + if (Object.prototype.hasOwnProperty.call(cameracounts, cameraid)) { var camera = cameracounts[cameraid]; var cameratext = "
"; cameratext += "" + cameraid + ""; @@ -22,8 +32,8 @@ _ParseAJAXDensity: function (cameradensy) { var densystext = ""; for (var densyid in cameradensy) { - if (cameradensy.hasOwnProperty(densyid)) { - if (this._DensitySettings.hasOwnProperty(densyid)) { + if (Object.prototype.hasOwnProperty.call(cameradensy, densyid)) { + if (Object.prototype.hasOwnProperty.call(this._DensitySettings, densyid)) { var densy = cameradensy[densyid]; var densytext = "
"; densytext += "" + this._DensitySettings[densyid].Alias + ""; @@ -34,8 +44,5 @@ } } document.getElementById("crwoddensy").innerHTML = densystext; - }, - _ParseAJAXSettings: function (json) { - this._DensitySettings = json["DensityArea"]; } }.Start(); \ No newline at end of file diff --git a/map-swagger.yml b/map-swagger.yml new file mode 100644 index 0000000..6ce3923 --- /dev/null +++ b/map-swagger.yml @@ -0,0 +1,312 @@ +openapi: "3.0.0" + +info: + version: 1.0.0 + title: Lora-Map + description: Swagger-File for the API of the Lora-Map + contact: + name: Philip Schell + email: philip.schell@fit.fraunhofer.de + license: + name: LGPL 3 + url: https://www.gnu.org/licenses/lgpl-3.0.html + +servers: + - url: http://localhost:8080 + +paths: + /api/json/camera: + get: + description: Get related data to Cameras + tags: + - api + responses: + 200: + description: ok + content: + application/json: + example: + Counter: + Haupteingang: + Lastcameradata: "04/08/2021 00:20:31" + Name: "Camera 1" + Total: 50 + Incoming: 35 + Outgoing: 15 + Density: + Hauptflaeche: + DensityCount: 10 + TimeStamp: "04/08/2021 00:20:31" + AverageFlowMagnitude: 5.2 + AverageFlowDirection: 175.2 + LastUpdate: "04/08/2021 00:20:31" + Fights: + Kneipe: + LastUpdate: "04/08/2021 00:20:31" + TimeStamp: "04/08/2021 00:20:31" + Situation: "fight" + FightProbability: 0.7 + + /api/json/position: + get: + description: Get related data to Positions + tags: + - api + responses: + 200: + description: ok + content: + application/json: + example: + Positions: + AA: + Rssi: 5.2 + Snr: 3.2 + Lorarecievedtime: "04/08/2021 00:20:31" + Recievedtime: "04/08/2021 00:20:31" + Latitude: 50.2 + Longitude: 7.8 + UTM: + MGRS: "32U MA 14357 61557" + Base: "32U MA" + FieldWidth: "14" + FieldHeight: "61" + Width: "357" + Height: "557" + Hdop: 1.2 + Lastgpspostime: "04/08/2021 00:20:31" + Battery: 4.2 + Batterysimple: 4 + Fix: true + Height: 60.2 + Name: "AA" + Icon: null + MenuIcon: null + Group: null + Alarms: + AA: + Rssi: 5.2 + Snr: 3.2 + Lorarecievedtime: "04/08/2021 00:20:31" + Recievedtime: "04/08/2021 00:20:31" + Latitude: 50.2 + Longitude: 7.8 + UTM: + MGRS: "32U MA 14357 61557" + Base: "32U MA" + FieldWidth: "14" + FieldHeight: "61" + Width: "357" + Height: "557" + Hdop: 1.2 + Lastgpspostime: "04/08/2021 00:20:31" + Battery: 4.2 + Batterysimple: 4 + Fix: true + Height: 60.2 + Name: "AA" + Icon: null + MenuIcon: null + Group: null + ButtonPressed: + - "04/08/2021 00:20:31" + + /api/json/sensor: + get: + description: Get related data to Sensors + tags: + - api + responses: + 200: + description: ok + content: + application/json: + example: + Enviroments: + Sensor1: + Name: "Sensor1" + Rssi: 50.2 + Snr: 11.2 + Temperature: 23.4 + Humidity: 43.2 + Windspeed: 12.5 + Lorarecievedtime: "04/08/2021 00:20:31" + Weather: + Warnungen: + - Body: "Es tritt leichter Frost zwischen -2 °C und -5 °C auf. Vor allem bei Aufklaren über Schnee sinken die Temperaturen auf Werte bis -9 °C." + From: "2021-04-08T13:54:00Z" + Headline: "Amtliche WARNUNG vor FROST" + Id: "Warnungen_Gemeinden.808111000.2.49.0.1.276.0.DWD.PVW.1617890040000.b2a1b3ea-db16-4992-920b-ea9c1b1a905f.DEU" + Instructions: "" + Level: "minor" + Location: "Stadt Stuttgart" + To: "2021-04-09T07:00:00Z" + Type: "frost" + + /api/json/settings: + get: + description: Get related data to Settings + tags: + - api + responses: + 200: + description: ok + content: + application/json: + example: + Startloclat: 50.2 + Startloclon: 7.2 + Grid: + Major: + - from: + - 50.2 + - 7.2 + to: + - 50.2 + - 7.1 + Minor: + - from: + - 50.1 + - 7.2 + - to: + - 50.1 + - 7.1 + FightDedection: + fight: + Alias: "fightcam" + Level: 0.7 + Polygon: + - - 50.2 + - 7.2 + - - 50.1 + - 7.2 + - - 50.2 + - 7.1 + DensityArea: + dens: + Alias: "denscam" + Maximum: + Polygon: + - - 50.2 + - 7.2 + - - 50.1 + - 7.2 + - - 50.2 + - 7.1 + Sensors: + temp: + Coordinates: + - 50.2 + - 7.2 + Level: 20 + Alias: "Temperatur" + Layers: + online: + title: Online Map + url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' + attribution: '© OpenStreetMap contributors' + minZoom: 1 + maxZoom: 19 + GeoLayer: {} + + /api/time: + get: + description: Get the current server time + tags: + - api + responses: + 200: + description: ok + content: + application/json: + example: + utc: "04/09/2021 21:55:37" + + + /api/svg/marker.svg: + get: + description: Get a complete marker for the map + tags: + - marker + responses: + 200: + description: ok + + /api/svg/person.svg: + get: + description: Get an person icon + tags: + - marker + responses: + 200: + description: ok + + + /admin/login: + post: + description: Login into the Admin pannel, is needed for every other /admin reqeust. Returns a session cookie + tags: + - admin + responses: + 307: + description: Redirect to /admin if login was successful and to /admin/login.html if not. + + /admin/api/json/name: + get: + description: Get the raw content of names.json + tags: + - admin + responses: + 200: + description: Returns the raw content + 403: + description: You are not logged in, see /admin/login for infos. + put: + description: Save the raw content to names.json + tags: + - admin + responses: + 200: + description: Ok if valid json in the request + 403: + description: You are not logged in, see /admin/login for infos. + + /admin/api/json/geo: + get: + description: Get the raw content of geo.json + tags: + - admin + responses: + 200: + description: Returns the raw content + 403: + description: You are not logged in, see /admin/login for infos. + put: + description: Save the raw content to geo.json + tags: + - admin + responses: + 200: + description: Ok if valid json in the request + 403: + description: You are not logged in, see /admin/login for infos. + + /admin/api/json/setting: + get: + description: Get the raw content of settings.json + tags: + - admin + responses: + 200: + description: Returns the raw content + 403: + description: You are not logged in, see /admin/login for infos. + put: + description: Save the raw content to settings.json + tags: + - admin + responses: + 200: + description: Ok if valid json in the request + 403: + description: You are not logged in, see /admin/login for infos. \ No newline at end of file