Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
d90230ef14 | |||
26c6f75ae9 | |||
3705d78dcd | |||
7dc841fe5c |
2
.github/workflows/dotnetcore.yml
vendored
2
.github/workflows/dotnetcore.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
||||
- name: Install dotnet
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 3.0.100
|
||||
dotnet-version: '3.1.x'
|
||||
|
||||
- name: Build with dotnet
|
||||
run: dotnet build Lora-Map.sln --configuration Release
|
||||
|
14
Lora-Map.sln
14
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
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RootNamespace>Fraunhofer.Fit.IoT.LoraMap</RootNamespace>
|
||||
<AssemblyName>Lora-Map</AssemblyName>
|
||||
<ApplicationManifest>Adminrights.manifest</ApplicationManifest>
|
||||
@ -10,15 +10,16 @@
|
||||
<Description>Displays Items with Coordinates from Mqtt on a Map</Description>
|
||||
<Company>Fraunhofer FIT</Company>
|
||||
<PackageId>LoraMap.IoT.Fit.Fraunhofer</PackageId>
|
||||
<Copyright>Copyright © Fraunhofer FIT, BlubbFish 2018 - 20.01.2020</Copyright>
|
||||
<Copyright>Copyright © Fraunhofer FIT, BlubbFish 2018 - 10.04.2021</Copyright>
|
||||
<Authors>BlubbFish</Authors>
|
||||
<Version>1.3.0</Version>
|
||||
<Version>1.3.1</Version>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageProjectUrl>https://github.com/MONICA-Project/lora-map</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/MONICA-Project/lora-map.git</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<NeutralLanguage>de-DE</NeutralLanguage>
|
||||
<PackageReleaseNotes>
|
||||
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 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Librarys\Coordinates\CoordinateSharp\CoordinateSharp_Core.csproj" />
|
||||
<ProjectReference Include="..\..\Librarys\litjson\litjson\litjson_Core.csproj" />
|
||||
<ProjectReference Include="..\..\Librarys\mqtt\M2Mqtt\M2Mqtt_Core.csproj" />
|
||||
<ProjectReference Include="..\..\Utils\Bot-Utils\Bot-Utils\Bot-Utils_Core.csproj" />
|
||||
<ProjectReference Include="..\..\Utils\ConnectorDataMqtt\ConnectorDataMqtt\ConnectorDataMqtt_Core.csproj" />
|
||||
<ProjectReference Include="..\..\Utils\Utils-IoT\Utils-IoT\Utils-IoT_Core.csproj" />
|
||||
<ProjectReference Include="..\..\Utils\Utils\Utils\Utils_Core.csproj" />
|
||||
<ProjectReference Include="..\..\Librarys\Coordinates\CoordinateSharp\CoordinateSharp.csproj" />
|
||||
<ProjectReference Include="..\..\Librarys\litjson\litjson\litjson.csproj" />
|
||||
<ProjectReference Include="..\..\Librarys\mqtt\M2Mqtt\M2Mqtt.csproj" />
|
||||
<ProjectReference Include="..\..\Utils\Bot-Utils\Bot-Utils\Bot-Utils.csproj" />
|
||||
<ProjectReference Include="..\..\Utils\ConnectorDataMqtt\ConnectorDataMqtt\ConnectorDataMqtt.csproj" />
|
||||
<ProjectReference Include="..\..\Utils\Utils-IoT\Utils-IoT\Utils-IoT.csproj" />
|
||||
<ProjectReference Include="..\..\Utils\Utils\Utils\Utils.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -57,7 +58,9 @@
|
||||
<Content Include="../CONTRIBUTING.md" />
|
||||
<Content Include="../LICENSE" />
|
||||
<Content Include="../README.md" />
|
||||
<Content Include="../map-swagger.yml" />
|
||||
<Content Include="../.github/workflows/dotnetcore.yml" />
|
||||
<Content Include="../doc/Manual.md" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -70,7 +73,16 @@
|
||||
<None Update="resources\admin\index.html">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="resources\admin\js\menu.js">
|
||||
<None Update="resources\admin\js\adminmenu.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="resources\admin\js\eximport.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="resources\admin\js\nameseditor.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="resources\admin\js\settings.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="resources\admin\login.html">
|
||||
|
@ -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<String, Tuple<String, String>> datastorage = new SortedDictionary<String, Tuple<String, String>>() {
|
||||
{ "name", new Tuple<String, String>("names", "NamesUpdate") },
|
||||
{ "geo", new Tuple<String, String>("geo", "GeoUpdate") },
|
||||
{ "setting", new Tuple<String, String>("settings", "SettingsUpdate") }
|
||||
};
|
||||
|
||||
private readonly Dictionary<Int64, AdminSession> session = new Dictionary<Int64, AdminSession>();
|
||||
private readonly Dictionary<String, String> 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<String, JsonData> ret = new Dictionary<String, JsonData>();
|
||||
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<AdminEvent>(updatenotifier)?.Invoke(this, new EventArgs());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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"];
|
||||
|
@ -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 &&
|
@ -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; }
|
62
Lora-Map/Model/Camera/CameraModel.cs
Normal file
62
Lora-Map/Model/Camera/CameraModel.cs
Normal file
@ -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<CameraModel> {
|
||||
private readonly Object lockFight = new Object();
|
||||
private readonly Object lockCount = new Object();
|
||||
private readonly Object lockDensy = new Object();
|
||||
|
||||
public SortedDictionary<String, CameraCounter> Counter {
|
||||
get; private set;
|
||||
}
|
||||
public SortedDictionary<String, CameraDensity> Density {
|
||||
get; private set;
|
||||
}
|
||||
public SortedDictionary<String, CameraFights> Fights {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
protected CameraModel() {
|
||||
this.Counter = new SortedDictionary<String, CameraCounter>();
|
||||
this.Density = new SortedDictionary<String, CameraDensity>();
|
||||
this.Fights = new SortedDictionary<String, CameraFights>();
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 += "<style type=\"text/css\">#marker-bg {display: none;}#marker-name {display: none;}</style>";
|
||||
}
|
||||
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 += "<style type=\"text/css\">#marker-icon #person { display: inline; }</style>";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "person-org":
|
||||
XmlNodeList xmlpersonorg = this.svg.DocumentElement.SelectNodes("//*[local-name()='defs'][@id='people-def']");
|
||||
if (xmlpersonorg.Count == 1) {
|
||||
xmlpersonorg.Item(0).InnerXml += "<style type=\"text/css\">#person-layer-org #person-layer-org-"+ keyvalue[1] + " { display: inline; }</style>";
|
||||
}
|
||||
break;
|
||||
case "person-funct":
|
||||
XmlNodeList xmlpersonfunct = this.svg.DocumentElement.SelectNodes("//*[local-name()='defs'][@id='people-def']");
|
||||
if (xmlpersonfunct.Count == 1) {
|
||||
xmlpersonfunct.Item(0).InnerXml += "<style type=\"text/css\">#person-layer-funct #person-layer-funct-" + keyvalue[1] + " { display: inline; }</style>";
|
||||
}
|
||||
break;
|
||||
case "person-rang":
|
||||
XmlNodeList xmlpersonrang = this.svg.DocumentElement.SelectNodes("//*[local-name()='defs'][@id='people-def']");
|
||||
if (xmlpersonrang.Count == 1) {
|
||||
xmlpersonrang.Item(0).InnerXml += "<style type=\"text/css\">#person-layer-rang #person-layer-rang-" + keyvalue[1] + " { display: inline; }</style>";
|
||||
}
|
||||
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 += "<style type=\"text/css\">#person-layer-typ #person-layer-typ-" + keyvalue[1] + " { display: inline; }</style>";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override String ToString() => this.svg.OuterXml;
|
||||
}
|
||||
}
|
@ -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<DateTime, String> buttonhistory = new SortedDictionary<DateTime, String>();
|
||||
|
||||
public List<DateTime> 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) {
|
@ -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<String, String> 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<String, String> 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<String, String>(icon, menu);
|
||||
}
|
||||
|
||||
public static Boolean CheckJson(JsonData json) =>
|
||||
json.ContainsKey("BatteryLevel") && (json["BatteryLevel"].IsDouble || json["BatteryLevel"].IsInt)
|
||||
&& json.ContainsKey("Gps") && json["Gps"].IsObject
|
73
Lora-Map/Model/Position/PositionModel.cs
Normal file
73
Lora-Map/Model/Position/PositionModel.cs
Normal file
@ -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<PositionModel> {
|
||||
private readonly Object lockData = new Object();
|
||||
private readonly Object lockPanic = new Object();
|
||||
private JsonData marker;
|
||||
|
||||
public SortedDictionary<String, PositionItem> Positions {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public SortedDictionary<String, PositionAlarm> Alarms {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
protected PositionModel() {
|
||||
this.Positions = new SortedDictionary<String, PositionItem>();
|
||||
this.Alarms = new SortedDictionary<String, PositionAlarm>();
|
||||
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<String, PositionItem> 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", "{}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
41
Lora-Map/Model/Sensor/SensorModel.cs
Normal file
41
Lora-Map/Model/Sensor/SensorModel.cs
Normal file
@ -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<SensorModel> {
|
||||
private readonly Object lockSensor = new Object();
|
||||
|
||||
public SortedDictionary<String, SensorEnviromentData> Enviroments {
|
||||
get; private set;
|
||||
}
|
||||
public SensorWeather Weather {
|
||||
get; private set;
|
||||
}
|
||||
|
||||
protected SensorModel() {
|
||||
this.Enviroments = new SortedDictionary<String, SensorEnviromentData>();
|
||||
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();
|
||||
}
|
||||
}
|
@ -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<Warning> Warnungen { get; private set; }
|
||||
|
||||
public WeatherWarnings(Settings settings) {
|
||||
this.settings = settings;
|
||||
this.StartBackgroundThread();
|
||||
}
|
||||
public SensorWeather() => this.StartBackgroundThread();
|
||||
|
||||
private void StartBackgroundThread() {
|
||||
this.Warnungen = new List<Warning>();
|
||||
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<Warning> ret = new List<Warning>();
|
||||
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;
|
@ -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<Int32> weatherCellIDs = new List<Int32>();
|
||||
public class Settings : OwnSingeton<Settings> {
|
||||
|
||||
private Int32 gridradius;
|
||||
|
||||
public Double Startloclat { get; private set; }
|
||||
public Double Startloclon { get; private set; }
|
||||
public Dictionary<String, List<Dictionary<String, List<Double>>>> Grid { get; private set; }
|
||||
public Dictionary<String, Fight> FightDedection { get; private set; }
|
||||
public Dictionary<String, Density> DensityArea { get; private set; }
|
||||
public Dictionary<String, Sensor> 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<String, Fight> fights = new Dictionary<String, Fight>();
|
||||
foreach (KeyValuePair<String, JsonData> entry in json["FightDedection"]) {
|
||||
foreach(KeyValuePair<String, JsonData> entry in json["FightDedection"]) {
|
||||
Fight fight = new Fight {
|
||||
Polygon = new List<List<Double>>()
|
||||
};
|
||||
if(entry.Value.ContainsKey("Poly") && entry.Value["Poly"].IsArray) {
|
||||
foreach (JsonData coord in entry.Value["Poly"]) {
|
||||
foreach(JsonData coord in entry.Value["Poly"]) {
|
||||
List<Double> coords = new List<Double>();
|
||||
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<String, Density> densitys = new Dictionary<String, Density>();
|
||||
foreach (KeyValuePair<String, JsonData> entry in json["CrwodDensity"]) {
|
||||
foreach(KeyValuePair<String, JsonData> entry in json["CrwodDensity"]) {
|
||||
Density density = new Density {
|
||||
Polygon = new List<List<Double>>()
|
||||
};
|
||||
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<Double> coords = new List<Double>();
|
||||
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<String, Sensor> sensors = new Dictionary<String, Sensor>();
|
||||
@ -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<String, List<Dictionary<String, List<Double>>>> {
|
||||
this.External.Grid = new Dictionary<String, List<Dictionary<String, List<Double>>>> {
|
||||
{ "Major", new List<Dictionary<String, List<Double>>>() },
|
||||
{ "Minor", new List<Dictionary<String, List<Double>>>() }
|
||||
};
|
||||
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<String, List<Double>> {
|
||||
if(i % 100 == 0) {
|
||||
this.External.Grid["Major"].Add(new Dictionary<String, List<Double>> {
|
||||
{ "from", new List<Double> {
|
||||
TopLeft.Latitude.DecimalDegree,
|
||||
TopLeft.Longitude.DecimalDegree
|
||||
@ -149,7 +165,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.Grid["Minor"].Add(new Dictionary<String, List<Double>> {
|
||||
this.External.Grid["Minor"].Add(new Dictionary<String, List<Double>> {
|
||||
{ "from", new List<Double> {
|
||||
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<String, List<Double>> {
|
||||
if(i % 100 == 0) {
|
||||
this.External.Grid["Major"].Add(new Dictionary<String, List<Double>> {
|
||||
{ "from", new List<Double> {
|
||||
BottomLeft.Latitude.DecimalDegree,
|
||||
BottomLeft.Longitude.DecimalDegree
|
||||
@ -180,7 +196,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.Grid["Minor"].Add(new Dictionary<String, List<Double>> {
|
||||
this.External.Grid["Minor"].Add(new Dictionary<String, List<Double>> {
|
||||
{ "from", new List<Double> {
|
||||
BottomLeft.Latitude.DecimalDegree,
|
||||
BottomLeft.Longitude.DecimalDegree
|
||||
@ -196,24 +212,117 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model {
|
||||
}
|
||||
}
|
||||
|
||||
public List<Int32> GetWeatherCellIds() => this.weatherCellIDs;
|
||||
private void FindMapLayer() {
|
||||
this.External.Layers = new Dictionary<String, Dictionary<String, Object>> {
|
||||
{ "online", new Dictionary<String, Object>() {
|
||||
{ "title", "Online Map" },
|
||||
{ "url", "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" },
|
||||
{ "attribution", "© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> 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<String, Object> entry = new Dictionary<String, Object> {
|
||||
{ "title", (String)map["name"] },
|
||||
{ "url", (String)map["tiles"][0] },
|
||||
{ "attribution", (String)map["attribution"] },
|
||||
{ "minZoom", (Int32)map["minzoom"] },
|
||||
{ "maxZoom", (Int32)map["maxzoom"] },
|
||||
{ "bounds", new Dictionary<String, Object>() {
|
||||
{ "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<List<Double>> Polygon { get; set; }
|
||||
public Int32 Maximum { get; set; }
|
||||
public String Alias { get; set; }
|
||||
public List<List<Double>> Polygon {
|
||||
get; set;
|
||||
}
|
||||
public Int32 Maximum {
|
||||
get; set;
|
||||
}
|
||||
public String Alias {
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
|
||||
public struct Fight {
|
||||
public List<List<Double>> Polygon { get; set; }
|
||||
public Double Level { get; set; }
|
||||
public String Alias { get; set; }
|
||||
public List<List<Double>> Polygon {
|
||||
get; set;
|
||||
}
|
||||
public Double Level {
|
||||
get; set;
|
||||
}
|
||||
public String Alias {
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
|
||||
public struct Sensor {
|
||||
public List<Double> Coordinates { get; set; }
|
||||
public Double Level { get; set; }
|
||||
public String Alias { get; set; }
|
||||
public List<Double> 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<String, List<Dictionary<String, List<Double>>>> Grid {
|
||||
get; set;
|
||||
} = new Dictionary<String, List<Dictionary<String, List<Double>>>>();
|
||||
public Dictionary<String, Fight> FightDedection {
|
||||
get; set;
|
||||
} = new Dictionary<String, Fight>();
|
||||
public Dictionary<String, Density> DensityArea {
|
||||
get; set;
|
||||
} = new Dictionary<String, Density>();
|
||||
public Dictionary<String, Sensor> Sensors {
|
||||
get; set;
|
||||
} = new Dictionary<String, Sensor>();
|
||||
public Dictionary<String, Dictionary<String, Object>> Layers {
|
||||
get; set;
|
||||
} = new Dictionary<String, Dictionary<String, Object>>();
|
||||
public JsonData GeoLayer {
|
||||
get; set;
|
||||
}
|
||||
}
|
||||
|
||||
public class PrivateSettings {
|
||||
public List<Int32> WeatherCellIDs { get; set; } = new List<Int32>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
116
Lora-Map/Model/Svg/SVGFile.cs
Normal file
116
Lora-Map/Model/Svg/SVGFile.cs
Normal file
@ -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<Double> viewbox;
|
||||
private readonly Boolean withSvgHeader;
|
||||
protected List<String> css = new List<String>();
|
||||
|
||||
public SVGFile(String query, Double width, Double heigt, List<Double> 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<String, String> config) {
|
||||
String query = "";
|
||||
if(config.Count > 0) {
|
||||
query += "?";
|
||||
List<String> queryparts = new List<String>();
|
||||
foreach(KeyValuePair<String, String> 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 += "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n";
|
||||
svg += $"<svg width=\"{this.width.ToString(CultureInfo.InvariantCulture)}mm\" height=\"{this.height.ToString(CultureInfo.InvariantCulture)}mm\" viewBox=\"";
|
||||
foreach(Double item in this.viewbox) {
|
||||
svg += item.ToString(CultureInfo.InvariantCulture) + " ";
|
||||
}
|
||||
svg += "\" preserveAspectRatio=\"xMinYMin slice\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n";
|
||||
}
|
||||
if(this.css.Count > 0) {
|
||||
svg += "<defs><style type=\"text/css\">\n";
|
||||
foreach(String item in this.css) {
|
||||
svg += item + "\n";
|
||||
}
|
||||
svg += "</style></defs>\n";
|
||||
}
|
||||
svg += this.DrawSvgContent();
|
||||
if(this.withSvgHeader) {
|
||||
svg += "</svg>\n";
|
||||
}
|
||||
return svg;
|
||||
}
|
||||
}
|
||||
}
|
66
Lora-Map/Model/Svg/SVGMarker.cs
Normal file
66
Lora-Map/Model/Svg/SVGMarker.cs
Normal file
@ -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<Double>() { 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<String, String> GenerateConfig(JsonData json, String name) {
|
||||
Dictionary<String, String> config = new Dictionary<String, String>();
|
||||
if(name != "") {
|
||||
config.Add("name", name);
|
||||
}
|
||||
if(json.ContainsKey("person") && json["person"].IsObject) {
|
||||
config.Add("icon", "person");
|
||||
Dictionary<String, String> personconfig = SVGPerson.GenerateConfig(json["person"]);
|
||||
personconfig.ToList().ForEach(x => config.Add(x.Key, x.Value));
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
protected override String DrawSvgContent() {
|
||||
String svg = "<g inkscape:groupmode=\"layer\" id=\"marker-bg\" inkscape:label=\"Marker\">\n";
|
||||
svg += "<rect style=\"fill:#ffffff;stroke:#000000;stroke-width:1.5px;\" width=\"82.5\" height=\"110\" x=\"2\" y=\"0.75\" />\n";
|
||||
svg += "<path style=\"stroke:#000000;stroke-width:1.5px;\" d=\"m 2,110.75 0,8.5\" />\n";
|
||||
svg += "<circle style=\"fill:#000000;\" cx=\"2\" cy=\"119.25\" r=\"2\" />\n";
|
||||
svg += "</g>\n";
|
||||
|
||||
svg += "<g inkscape:groupmode=\"layer\" id=\"marker-name\" inkscape:label=\"Name\">\n";
|
||||
svg += $"<text><tspan x=\"5\" y=\"20\" id=\"marker-name-text\">{this.name}</tspan></text>\n";
|
||||
svg += "</g>\n";
|
||||
|
||||
if(this.icon == "person") {
|
||||
svg += "<g inkscape:groupmode=\"layer\" id=\"marker-icon\" inkscape:label=\"Icon\" transform=\"translate(42.5 45) scale(0.8)\">\n";
|
||||
svg += new SVGPerson(this.query, false);
|
||||
svg += "</g>\n";
|
||||
}
|
||||
return svg;
|
||||
}
|
||||
}
|
||||
}
|
198
Lora-Map/Model/Svg/SVGPerson.cs
Normal file
198
Lora-Map/Model/Svg/SVGPerson.cs
Normal file
@ -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<Double>() { -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<String, String> GenerateConfig(JsonData json) {
|
||||
Dictionary<String, String> config = new Dictionary<String, String>();
|
||||
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<String> typs = new List<String>();
|
||||
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 += "<g inkscape:groupmode=\"layer\" id=\"person-layer-org\" inkscape:label=\"Organisation\">\n";
|
||||
svg += $"<g inkscape:groupmode=\"layer\" id=\"person-layer-org-{this.organisation}\" inkscape:label=\"{this.orglookup[this.organisation].Name}\">\n";
|
||||
svg += $"<rect style=\"fill: {this.orglookup[this.organisation].Color}\" height=\"50\" width=\"50\" transform=\"rotate(45)\"/>\n";
|
||||
svg += "</g>\n";
|
||||
svg += "</g>\n";
|
||||
}
|
||||
if(this.function != null && this.funclookup.ContainsKey(this.function)) {
|
||||
svg += "<g inkscape:groupmode=\"layer\" id=\"person-layer-funct\" inkscape:label=\"Funktion\">\n";
|
||||
svg += $"<g inkscape:groupmode=\"layer\" id=\"person-layer-funct-{this.function}\" inkscape:label=\"{this.funclookup[this.function].Name}\">\n";
|
||||
svg += $"<path d=\"{this.funclookup[this.function].Path}\" />\n";
|
||||
svg += "</g>\n";
|
||||
svg += "</g>\n";
|
||||
}
|
||||
if(this.rang != null && this.ranglookup.ContainsKey(this.rang)) {
|
||||
svg += "<g inkscape:groupmode=\"layer\" id=\"person-layer-rang\" inkscape:label=\"Rang\">\n";
|
||||
svg += $"<g inkscape:groupmode=\"layer\" id=\"person-layer-rang-{this.rang}\" inkscape:label=\"{this.ranglookup[this.rang].Name}\">\n";
|
||||
svg += "<g style=\"display: inline;\">\n";
|
||||
foreach(Double item in this.ranglookup[this.rang].Circles) {
|
||||
svg += $"<circle cx=\"{item.ToString(CultureInfo.InvariantCulture)}\" cy=\"-8\" r=\"3\" />\n";
|
||||
}
|
||||
svg += "</g>\n";
|
||||
svg += "</g>\n";
|
||||
svg += "</g>\n";
|
||||
}
|
||||
if(this.text != null || this.typs != null && this.typs.All(x => this.typlookup.ContainsKey(x))) {
|
||||
svg += "<g inkscape:groupmode=\"layer\" id=\"person-layer-typ\" inkscape:label=\"Typ\">\n";
|
||||
if(this.text != null && this.typs == null) {
|
||||
svg += $"<text><tspan y=\"42\" x=\"0\" id=\"person-layer-typ-text\">{this.text}</tspan></text>\n";
|
||||
}
|
||||
if(this.text == null && this.typs != null && this.typs.All(x => this.typlookup.ContainsKey(x))) {
|
||||
foreach(String typ in this.typs) {
|
||||
svg += $"<g id=\"person-layer-typ-{typ}\" inkscape:label=\"{this.typlookup[typ].Name}\">\n";
|
||||
foreach(Tuple<Double, Double, Double, Double> item in this.typlookup[typ].Lines) {
|
||||
svg += $"<line x1=\"{item.Item1.ToString(CultureInfo.InvariantCulture)}\" y1=\"{item.Item2.ToString(CultureInfo.InvariantCulture)}\" x2=\"{item.Item3.ToString(CultureInfo.InvariantCulture)}\" y2=\"{item.Item4.ToString(CultureInfo.InvariantCulture)}\" />\n";
|
||||
}
|
||||
svg += "</g>\n";
|
||||
}
|
||||
}
|
||||
svg += "</g>\n";
|
||||
}
|
||||
return svg;
|
||||
}
|
||||
|
||||
private readonly Dictionary<String, Organistaion> orglookup = new Dictionary<String, Organistaion>() {
|
||||
{ "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<String, Funktion> funclookup = new Dictionary<String, Funktion>() {
|
||||
{ "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<String, Rang> ranglookup = new Dictionary<String, Rang>() {
|
||||
{ "trupp", new Rang("Truppführer", new List<Double>() { 0 }) },
|
||||
{ "grupp", new Rang("Gruppenführer", new List<Double>() { -4.5, 4.5 }) },
|
||||
{ "zug", new Rang("Zugführer", new List<Double>() { -9, 0, 9 }) }
|
||||
};
|
||||
private readonly Dictionary<String, Typ> typlookup = new Dictionary<String, Typ>() {
|
||||
{ "loesch", new Typ("Brandbekämpfung/Löscheinsatz", new List<Tuple<Double, Double, Double, Double>>() { new Tuple<Double, Double, Double, Double>(-35, 35.5, 35, 35.5), new Tuple<Double, Double, Double, Double>(17.5, 35.5, 25, 26), new Tuple<Double, Double, Double, Double>(17.5, 35.5, 25, 44) }) },
|
||||
{ "sani", new Typ("Rettungswesen, Sanitätswesen, Gesundheitswesen", new List<Tuple<Double, Double, Double, Double>>() { new Tuple<Double, Double, Double, Double>(0, 0, 0, 70), new Tuple<Double, Double, Double, Double>(-35, 35.5, 35, 35.5) }) },
|
||||
{ "betreu", new Typ("Betreuung", new List<Tuple<Double, Double, Double, Double>>() { new Tuple<Double, Double, Double, Double>(-17, 53, 0, 35.5), new Tuple<Double, Double, Double, Double>(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<Double> Circles {
|
||||
get;
|
||||
}
|
||||
public Rang(String name, List<Double> circles) {
|
||||
this.Name = name;
|
||||
this.Circles = circles;
|
||||
}
|
||||
}
|
||||
private struct Typ {
|
||||
public String Name {
|
||||
get;
|
||||
}
|
||||
public List<Tuple<Double, Double, Double, Double>> Lines {
|
||||
get;
|
||||
}
|
||||
public Typ(String name, List<Tuple<Double, Double, Double, Double>> lines) {
|
||||
this.Name = name;
|
||||
this.Lines = lines;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
42
Lora-Map/Model/Svg/SvgModel.cs
Normal file
42
Lora-Map/Model/Svg/SvgModel.cs
Normal file
@ -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<SvgModel> {
|
||||
private readonly Dictionary<String, SVGFile> svgtable = new Dictionary<String, SVGFile>();
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
@ -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<String, PositionItem> positions = new SortedDictionary<String, PositionItem>();
|
||||
private readonly SortedDictionary<String, AlarmItem> alarms = new SortedDictionary<String, AlarmItem>();
|
||||
private readonly SortedDictionary<String, Camera> counter = new SortedDictionary<String, Camera>();
|
||||
private readonly SortedDictionary<String, Crowd> density = new SortedDictionary<String, Crowd>();
|
||||
private readonly SortedDictionary<String, Fight> fights = new SortedDictionary<String, Fight>();
|
||||
private readonly SortedDictionary<String, EnviromentData> sensors = new SortedDictionary<String, EnviromentData>();
|
||||
private JsonData marker;
|
||||
private readonly Settings settings;
|
||||
private readonly WeatherWarnings weather;
|
||||
private readonly Dictionary<String, Marker> markertable = new Dictionary<String, Marker>();
|
||||
private readonly SortedDictionary<String, Object> jsonapi = new SortedDictionary<String, Object>() {
|
||||
{ "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<String, String> 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<String, PositionItem> 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<String, Object>() {
|
||||
{ "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<String, Object>() {
|
||||
{ "currenttime", new Dictionary<String, DateTime>() { { "utc", DateTime.UtcNow } } }
|
||||
}, cont);
|
||||
} else if (cont.Request.Url.PathAndQuery.StartsWith("/getonce")) {
|
||||
return SendJsonResponse(new Dictionary<String, Object>() {
|
||||
{ "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<String, Object> ret = new Dictionary<String, Object>();
|
||||
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<String, DateTime>() { { "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<String, Dictionary<String, Object>> FindMapLayer() {
|
||||
Dictionary<String, Dictionary<String, Object>> ret = new Dictionary<String, Dictionary<String, Object>> {
|
||||
{ "online", new Dictionary<String, Object>() {
|
||||
{ "title", "Online Map" },
|
||||
{ "url", "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" },
|
||||
{ "attribution", "© <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> 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<String, Object> entry = new Dictionary<String, Object> {
|
||||
{ "title", (String)map["name"] },
|
||||
{ "url", (String)map["tiles"][0] },
|
||||
{ "attribution", (String)map["attribution"] },
|
||||
{ "minZoom", (Int32)map["minzoom"] },
|
||||
{ "maxZoom", (Int32)map["maxzoom"] },
|
||||
{ "bounds", new Dictionary<String, Object>() {
|
||||
{ "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();
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
HOMEDIR=$HOME
|
||||
ROOT="$HOMEDIR/deb"
|
||||
OUTPUT="../bin/Release/netcoreapp3.0"
|
||||
OUTPUT="../bin/Release/netcoreapp3.1"
|
||||
|
||||
DEBNAME="loramap"
|
||||
CSPROJFILE="Lora-Map.csproj"
|
||||
|
@ -5,7 +5,6 @@
|
||||
<meta charset="utf-8" />
|
||||
<title>Adminpannel Lora-Map</title>
|
||||
<link rel="stylesheet" type="text/css" href="css/global.css" />
|
||||
<script type="text/javascript" src="js/menu.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="header">Adminpannel Lora-Map</div>
|
||||
@ -18,5 +17,9 @@
|
||||
</ul>
|
||||
</div>
|
||||
<div id="content">Wilkommen im Adminbereich</div>
|
||||
<script type="text/javascript" src="js/adminmenu.js"></script>
|
||||
<script type="text/javascript" src="js/eximport.js"></script>
|
||||
<script type="text/javascript" src="js/nameseditor.js"></script>
|
||||
<script type="text/javascript" src="js/settings.js"></script>
|
||||
</body>
|
||||
</html>
|
42
Lora-Map/resources/admin/js/adminmenu.js
Normal file
42
Lora-Map/resources/admin/js/adminmenu.js
Normal file
@ -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;
|
||||
}
|
||||
};
|
56
Lora-Map/resources/admin/js/eximport.js
Normal file
56
Lora-Map/resources/admin/js/eximport.js
Normal file
@ -0,0 +1,56 @@
|
||||
var ExImport = {
|
||||
//public functions
|
||||
ParseJson: function (jsonnames, jsongeo, jsonsettings) {
|
||||
html = "<div id='eximport'><div class='title'>Ex- und Import der Einstellungen</div>";
|
||||
html += "<div class='names'>names.json (Namen und Icons)<br/><textarea id='ex_names'></textarea> <img src='../icons/general/save.png' onclick='ExImport.SaveNames()' class='pointer'></div>";
|
||||
html += "<div class='names'>geo.json (Layer on the MAP) <a href='https://mapbox.github.io/togeojson/'>Kml Konverter</a><br/><textarea id='ex_geo'></textarea> <img src='../icons/general/save.png' onclick='ExImport.SaveGeo()' class='pointer'></div>";
|
||||
html += "<div class='names'>settings.json (Settings of the Map)<br/><textarea id='ex_settings'></textarea> <img src='../icons/general/save.png' onclick='ExImport.SaveSettings()' class='pointer'></div>";
|
||||
html += "</div>";
|
||||
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);
|
||||
}
|
||||
};
|
@ -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 = "<div id='nameeditor'><div class='title'>Namenseinträge in den Einstellungen</div>";
|
||||
html += "<table id='nametable' class='settingstable'>";
|
||||
html += "<thead><tr><th width='60'>ID</th><th width='250'>Name</th><th width='65'>Icon</th><th width='150'>Filter Gruppe</th><th width='50'></th></tr></thead>";
|
||||
html += "<tbody>";
|
||||
for (var id in namesconfig) {
|
||||
if (namesconfig.hasOwnProperty(id)) {
|
||||
var nameentry = namesconfig[id];
|
||||
html += "<tr>" +
|
||||
"<td>" + id + "</td>" +
|
||||
"<td>" + nameentry["name"] + "</td>";
|
||||
if (nameentry.hasOwnProperty("marker.svg")) {
|
||||
html += "<td>" + this.ParseIcon(nameentry["marker.svg"]) + "</td>";
|
||||
} else if (nameentry.hasOwnProperty("icon")) {
|
||||
html += "<td><img src='"+nameentry["icon"]+"'></td>";
|
||||
} else {
|
||||
html += "<td><img src='../js/leaflet/images/marker-icon.png'></td>";
|
||||
}
|
||||
var gfilter = typeof nameentry.Group === "undefined" ? "no" : nameentry.Group;
|
||||
html += "<td rel='" + gfilter + "'>" + this.filterGropus[gfilter] + "</td>";
|
||||
html += "<td><img src='../icons/general/edit.png' onclick='NamesEditor.Edit(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Delete(this.parentNode.parentNode)' class='pointer'></td>" +
|
||||
"</tr>";
|
||||
}
|
||||
}
|
||||
html += "</tbody>";
|
||||
html += "<tfoot><tr><td></td><td></td><td></td><td></td><td><img src='../icons/general/add.png' onclick='NamesEditor.Add()' class='pointer'> <img src='../icons/general/save.png' onclick='NamesEditor.Save()' class='pointer'></td></tr></tfoot>";
|
||||
html += "</table>";
|
||||
document.getElementById("content").innerHTML = html + "</div>";
|
||||
},
|
||||
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 "<object data='"+url+"' type='image/svg+xml' style='height:50px; width:50px;'></object>";
|
||||
},
|
||||
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 = "<td><input style='width: 55px;'/></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 245px;'/></td>";
|
||||
newrow.innerHTML += "<td><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> wähle Icon</td>";
|
||||
newrow.innerHTML += "<td>" + this.CreateSelectBox("", "item", { item: "" }, this.filterGropus, null, null, true);
|
||||
newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='NamesEditor.SaveRow(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
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 = "<td><input style='width: 55px;' value='" + id + "'/></td>";
|
||||
el.innerHTML += "<td><input style='width: 245px;' value='" + name + "'/></td>";
|
||||
if (url === null) {
|
||||
el.innerHTML += "<td><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> wähle Icon</td>";
|
||||
} else {
|
||||
el.innerHTML += "<td><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> <object data='" + url + "' type='image/svg+xml' style='height:50px; width:50px;'></object></td>";
|
||||
}
|
||||
el.innerHTML += "<td>" + this.CreateSelectBox("", "item", { item: gfilter }, this.filterGropus, null, null, true);
|
||||
el.innerHTML += "<td><img src='../icons/general/save.png' onclick='NamesEditor.SaveRow(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
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 = "<td>" + id + "</td>" +
|
||||
"<td>" + name + "</td>";
|
||||
if (url === null) {
|
||||
el.innerHTML += "<td><img src='../js/leaflet/images/marker-icon.png'></td>";
|
||||
} else {
|
||||
el.innerHTML += "<td><object data='" + url +"' type='image/svg+xml' style='height:50px; width:50px;'></object></td>";
|
||||
}
|
||||
el.innerHTML += "<td rel='" + gfilter + "'>" + this.filterGropus[gfilter] + "</td>";
|
||||
el.innerHTML += "<td><img src='../icons/general/edit.png' onclick='NamesEditor.Edit(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Delete(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
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 = "<div class='innerbox'>" +
|
||||
"<div class='preview'><object id='markerprev' data='" + url + "' type='image/svg+xml' style='height:200px; width:200px;'></object></div>" +
|
||||
"<div class='controls'>" +
|
||||
this.CreateSelectBox("Typ", "icon", query, { "person": "Person" }, null, "iconeditor-type-") + "<br>" +
|
||||
"<div id='iconeditor-type-person' style='display: " + (query.hasOwnProperty("icon") && query["icon"] === "person" ? "block" : "none") + ";'>" +
|
||||
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" }) + "<br>" +
|
||||
this.CreateSelectBox("Funktion", "person-funct", query, { "sonder": "Sonder", "fueh": "Führung" }) + "<br>" +
|
||||
this.CreateSelectBox("Rang", "person-rang", query, { "trupp": "Trupp", "grupp": "Gruppe", "zug":"Zug" }) + "<br>" +
|
||||
"Text: <input onchange='NamesEditor.ChangeLinkPreview(\"person-text\",this.value);' value='" + (query.hasOwnProperty("person-text") ? query["person-text"] : "") + "'><br>" +
|
||||
this.CreateSelectBox("Typ", "person-typ", query, { "loesch": "Brandbekämpfung/Löscheinsatz", "sani": "Rettungswesen, Sanitätswesen, Gesundheitswesen", "betreu": "Betreuung" }, true) + "<br>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"<div class='save'><button onclick='NamesEditor.SaveIconEditor(\"" + el.id + "\"); '>Schließen</botton></div>" +
|
||||
"</div>";
|
||||
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 += "<select" + onchange + (typeof muliple !== "undefined" && muliple !== null ? " multiple" : "") + ">";
|
||||
if (typeof muliple === "undefined" || muliple === null) {
|
||||
html += "<option>---</option>";
|
||||
}
|
||||
for (var value in options) {
|
||||
if (query.hasOwnProperty(key) && query[key] === value) {
|
||||
html += "<option value='" + value + "' selected>" + options[value] + "</option>";
|
||||
} 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 += "<option value='" + value + "' selected>" + options[value] + "</option>";
|
||||
}
|
||||
}
|
||||
if (notinqueryarray) {
|
||||
html += "<option value='" + value + "'>" + options[value] + "</option>";
|
||||
}
|
||||
} else {
|
||||
html += "<option value='" + value + "'>" + options[value] + "</option>";
|
||||
}
|
||||
}
|
||||
html += "</select>";
|
||||
return html;
|
||||
},
|
||||
SaveIconEditor: function (id) {
|
||||
var cell = document.getElementById(id);
|
||||
cell.innerHTML = "<img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> <object data='" + document.getElementById("markerprev").data + "' type='image/svg+xml' style='height:50px; width:50px;'></object>";
|
||||
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 = "<div id='settingseditor'><div class='title'>Einstellungen</div>";
|
||||
html += "<div class='startloc'>Startpunkt: <input value='" + jsonsettings.StartPos.lat + "' id='startlat'> Lat, <input value='" + jsonsettings.StartPos.lon + "' id='startlon'> Lon</div>";
|
||||
html += "<div class='wetterwarnings'>CellId's für DWD-Wetterwarnungen: <input value='" + jsonsettings.CellIds.join(";") + "' id='wetterids'> (Trennen durch \";\", <a href='https://www.dwd.de/DE/leistungen/opendata/help/warnungen/cap_warncellids_csv.html'>cap_warncellids_csv</a>)</div>";
|
||||
html += "<div class='gridradius'>Radius für das Grid um den Startpunkt: <input value='" + jsonsettings.GridRadius + "' id='gridrad'>m</div>";
|
||||
html += "<div class='fightdedection'>Fight Dedection Kameras: <br>" + this._renderFightDedection(jsonsettings.FightDedection) + "</div>";
|
||||
html += "<div class='crowddensity'>Crowd Density Kameras: <br>" + this._renderCrowdDensity(jsonsettings.CrwodDensity) + "</div>";
|
||||
html += "<div class='sensorsettings'>Sensors: <br>" + this._renderSensorSettings(jsonsettings.Sensors) + "</div>";
|
||||
html += "<div class='savesettings'><img src='../icons/general/save.png' onclick='Settings.Save()' class='pointer'></div>";
|
||||
document.getElementById("content").innerHTML = html + "</div>";
|
||||
},
|
||||
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("<br>");
|
||||
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("<br>");
|
||||
|
||||
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 += "<table id='sensortable' class='settingstable'>";
|
||||
ret += "<thead><tr><th width='150'>ID</th><th width='150'>Alias</th><th width='250'>Koordinaten</th><th width='150'>Warn above</th><th width='50'></th></tr></thead>";
|
||||
|
||||
ret += "<tbody>";
|
||||
for (var id in json) {
|
||||
ret += "<tr>" +
|
||||
"<td>" + id + "</td>" +
|
||||
"<td>" + json[id].Alias + "</td>" +
|
||||
"<td>" + json[id].Poly.Lat + ";" + json[id].Poly.Lon + "</td>" +
|
||||
"<td>" + json[id].Level + "</td>" +
|
||||
"<td><img src='../icons/general/edit.png' onclick='Settings.EditSensor(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Delete(this.parentNode.parentNode)' class='pointer'></td>" +
|
||||
"</tr>";
|
||||
}
|
||||
ret += "</tbody>";
|
||||
|
||||
ret += "<tfoot><tr><td></td><td></td><td></td><td></td><td><img src='../icons/general/add.png' onclick='Settings.AddSensor()' class='pointer'></td></tr></tfoot>";
|
||||
ret += "</table>";
|
||||
return ret;
|
||||
},
|
||||
_renderFightDedection: function (json) {
|
||||
var ret = "";
|
||||
ret += "<table id='fighttable' class='settingstable'>";
|
||||
ret += "<thead><tr><th width='150'>ID</th><th width='250'>Koordinaten</th><th width='150'>Alias</th><th width='150'>Alertlimit</th><th width='50'></th></tr></thead>";
|
||||
ret += "<tbody>";
|
||||
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 += "<tr>" +
|
||||
"<td>" + id + "</td>" +
|
||||
"<td>" + coords.join("<br>") + "</td>" +
|
||||
"<td>" + json[id].Alias + "</td>" +
|
||||
"<td>" + json[id].Level + "</td>" +
|
||||
"<td><img src='../icons/general/edit.png' onclick='Settings.EditFight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Delete(this.parentNode.parentNode)' class='pointer'></td>" +
|
||||
"</tr>";
|
||||
}
|
||||
ret += "</tbody>";
|
||||
ret += "<tfoot><tr><td></td><td></td><td></td><td></td><td><img src='../icons/general/add.png' onclick='Settings.AddFight()' class='pointer'></td></tr></tfoot>";
|
||||
ret += "</table>";
|
||||
return ret;
|
||||
},
|
||||
_renderCrowdDensity: function (json) {
|
||||
var ret = "";
|
||||
ret += "<table id='crowdtable' class='settingstable'>";
|
||||
ret += "<thead><tr><th width='150'>ID</th><th width='200'>Personenanzahl</th><th width='250'>Koordinaten</th><th width='150'>Alias</th><th width='50'></th></tr></thead>";
|
||||
ret += "<tbody>";
|
||||
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 += "<tr>" +
|
||||
"<td>" + id + "</td>" +
|
||||
"<td>" + json[id].Count + "</td>" +
|
||||
"<td>" + coords.join("<br>") + "</td>" +
|
||||
"<td>" + json[id].Alias + "</td>" +
|
||||
"<td><img src='../icons/general/edit.png' onclick='Settings.EditDensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Delete(this.parentNode.parentNode)' class='pointer'></td>" +
|
||||
"</tr>";
|
||||
}
|
||||
ret += "</tbody>";
|
||||
ret += "<tfoot><tr><td></td><td></td><td></td><td></td><td><img src='../icons/general/add.png' onclick='Settings.AddDensity()' class='pointer'></td></tr></tfoot>";
|
||||
ret += "</table>";
|
||||
return ret;
|
||||
},
|
||||
AddSensor: function () {
|
||||
var newrow = document.createElement("tr");
|
||||
newrow.innerHTML = "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 250px;'/></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='Settings.SaveRowSensor(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
document.getElementById("sensortable").children[1].appendChild(newrow);
|
||||
},
|
||||
AddFight: function () {
|
||||
var newrow = document.createElement("tr");
|
||||
newrow.innerHTML = "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><textarea style='width: 240px;height: 60px;'></textarea></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='Settings.SaveRowfight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
document.getElementById("fighttable").children[1].appendChild(newrow);
|
||||
},
|
||||
AddDensity: function () {
|
||||
var newrow = document.createElement("tr");
|
||||
newrow.innerHTML = "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 195px;'/></td>";
|
||||
newrow.innerHTML += "<td><textarea style='width: 240px;height: 60px;'></textarea></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='Settings.SaveRowdensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
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 = "<td>" + el.children[0].children[0].value + "</td>" +
|
||||
"<td>" + el.children[1].children[0].value + "</td>" +
|
||||
"<td>" + coords + "</td>" +
|
||||
"<td>" + this._filterFloat(el.children[3].children[0].value) + "</td>" +
|
||||
"<td><img src='../icons/general/edit.png' onclick='Settings.EditSensor(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Delete(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
SaveRowfight: function (el) {
|
||||
var coords = el.children[1].children[0].value.replace(/\n/gi, "<br>");
|
||||
var coordscheck = coords.split("<br>");
|
||||
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 = "<td>" + el.children[0].children[0].value + "</td>" +
|
||||
"<td>" + coords + "</td>" +
|
||||
"<td>" + el.children[2].children[0].value + "</td>" +
|
||||
"<td>" + this._filterFloat(el.children[3].children[0].value) + "</td>" +
|
||||
"<td><img src='../icons/general/edit.png' onclick='Settings.EditFight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Delete(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
SaveRowdensity: function (el) {
|
||||
var coords = el.children[2].children[0].value.replace(/\n/gi, "<br>");
|
||||
var coordscheck = coords.split("<br>");
|
||||
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 = "<td>" + el.children[0].children[0].value + "</td>" +
|
||||
"<td>" + el.children[1].children[0].value + "</td>" +
|
||||
"<td>" + coords + "</td>" +
|
||||
"<td>" + el.children[3].children[0].value + "</td>" +
|
||||
"<td><img src='../icons/general/edit.png' onclick='Settings.EditDensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Delete(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
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 = "<td><input style='width: 145px;' value='" + el.children[0].innerText + "'/></td>" +
|
||||
"<td><input style='width: 145px;' value='" + el.children[1].innerText + "'/></td>" +
|
||||
"<td><input style='width: 250px;' value='" + el.children[2].innerText + "'/></td>" +
|
||||
"<td><input style='width: 145px;' value='" + el.children[3].innerText + "'/></td>" +
|
||||
"<td><img src='../icons/general/save.png' onclick='Settings.SaveRowSensor(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
EditFight: function (el) {
|
||||
el.innerHTML = "<td><input style='width: 145px;' value='" + el.children[0].innerText + "'/></td>" +
|
||||
"<td><textarea style='width: 240px;height: 60px;'>" + el.children[1].innerText + "</textarea></td>" +
|
||||
"<td><input style='width: 145px;' value='" + el.children[2].innerText + "'/></td>" +
|
||||
"<td><input style='width: 145px;' value='" + el.children[3].innerText + "'/></td>" +
|
||||
"<td><img src='../icons/general/save.png' onclick='Settings.SaveRowfight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
EditDensity: function (el) {
|
||||
el.innerHTML = "<td><input style='width: 145px;' value='" + el.children[0].innerText + "'/></td>" +
|
||||
"<td><input style='width: 195px;' value='" + el.children[1].innerText + "'/></td>" +
|
||||
"<td><textarea style='width: 240px;height: 60px;'>" + el.children[2].innerText + "</textarea></td>" +
|
||||
"<td><input style='width: 145px;' value='" + el.children[3].innerText + "'/></td>" +
|
||||
"<td><img src='../icons/general/save.png' onclick='Settings.SaveRowdensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
_filterFloat: function (value) {
|
||||
if (/^(\-|\+)?([0-9]+(\.[0-9]+)?|Infinity)$/.test(value)) {
|
||||
return Number(value);
|
||||
}
|
||||
return NaN;
|
||||
}
|
||||
};
|
||||
|
||||
var ExImport = {
|
||||
ParseJson: function (jsonnames, jsongeo, jsonsettings) {
|
||||
html = "<div id='eximport'><div class='title'>Ex- und Import der Einstellungen</div>";
|
||||
html += "<div class='names'>names.json (Namen und Icons)<br/><textarea id='ex_names'></textarea> <img src='../icons/general/save.png' onclick='ExImport.SaveNames()' class='pointer'></div>";
|
||||
html += "<div class='names'>geo.json (Layer on the MAP) <a href='https://mapbox.github.io/togeojson/'>Kml Konverter</a><br/><textarea id='ex_geo'></textarea> <img src='../icons/general/save.png' onclick='ExImport.SaveGeo()' class='pointer'></div>";
|
||||
html += "<div class='names'>settings.json (Settings of the Map)<br/><textarea id='ex_settings'></textarea> <img src='../icons/general/save.png' onclick='ExImport.SaveSettings()' class='pointer'></div>";
|
||||
html += "</div>";
|
||||
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);
|
||||
}
|
||||
};
|
304
Lora-Map/resources/admin/js/nameseditor.js
Normal file
304
Lora-Map/resources/admin/js/nameseditor.js
Normal file
@ -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 = "<td><input style='width: 55px;'/></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 245px;'/></td>";
|
||||
newrow.innerHTML += "<td><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> wähle Icon</td>";
|
||||
newrow.innerHTML += "<td>" + this.CreateSelectBox("", "item", { item: "" }, this.filterGropus, null, null, true);
|
||||
newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='NamesEditor.SaveRow(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
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 += "<select" + onchange + (typeof muliple !== "undefined" && muliple !== null ? " multiple" : "") + ">";
|
||||
if (typeof muliple === "undefined" || muliple === null) {
|
||||
html += "<option>---</option>";
|
||||
}
|
||||
for (var value in options) {
|
||||
if (Object.prototype.hasOwnProperty.call(query, key) && query[key] === value) {
|
||||
html += "<option value='" + value + "' selected>" + options[value] + "</option>";
|
||||
} 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 += "<option value='" + value + "' selected>" + options[value] + "</option>";
|
||||
}
|
||||
}
|
||||
if (notinqueryarray) {
|
||||
html += "<option value='" + value + "'>" + options[value] + "</option>";
|
||||
}
|
||||
} else {
|
||||
html += "<option value='" + value + "'>" + options[value] + "</option>";
|
||||
}
|
||||
}
|
||||
html += "</select>";
|
||||
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 = "<td><input style='width: 55px;' value='" + id + "'/></td>";
|
||||
el.innerHTML += "<td><input style='width: 245px;' value='" + name + "'/></td>";
|
||||
if (url === null) {
|
||||
el.innerHTML += "<td><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> wähle Icon</td>";
|
||||
} else {
|
||||
el.innerHTML += "<td><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> <object data='" + url + "' type='image/svg+xml' style='height:50px; width:50px;'></object></td>";
|
||||
}
|
||||
el.innerHTML += "<td>" + this.CreateSelectBox("", "item", { item: gfilter }, this.filterGropus, null, null, true);
|
||||
el.innerHTML += "<td><img src='../icons/general/save.png' onclick='NamesEditor.SaveRow(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
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 = "<div class='innerbox'>" +
|
||||
"<div class='preview'><object id='markerprev' data='" + url + "' type='image/svg+xml' style='height:200px; width:200px;'></object></div>" +
|
||||
"<div class='controls'>" +
|
||||
this.CreateSelectBox("Typ", "icon", query, { "person": "Person" }, null, "iconeditor-type-") + "<br>" +
|
||||
"<div id='iconeditor-type-person' style='display: " + (Object.prototype.hasOwnProperty.call(query, "icon") && query["icon"] === "person" ? "block" : "none") + ";'>" +
|
||||
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" }) + "<br>" +
|
||||
this.CreateSelectBox("Funktion", "person-funct", query, { "sonder": "Sonder", "fueh": "Führung" }) + "<br>" +
|
||||
this.CreateSelectBox("Rang", "person-rang", query, { "trupp": "Trupp", "grupp": "Gruppe", "zug": "Zug" }) + "<br>" +
|
||||
"Text: <input onchange='NamesEditor.ChangeLinkPreview(\"person-text\",this.value);' value='" + (Object.prototype.hasOwnProperty.call(query, "person-text") ? query["person-text"] : "") + "'><br>" +
|
||||
this.CreateSelectBox("Typ", "person-typ", query, { "loesch": "Brandbekämpfung/Löscheinsatz", "sani": "Rettungswesen, Sanitätswesen, Gesundheitswesen", "betreu": "Betreuung" }, true) + "<br>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"<div class='save'><button onclick='NamesEditor.SaveIconEditor(\"" + el.id + "\"); '>Schließen</botton></div>" +
|
||||
"</div>";
|
||||
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 "<object data='" + url + "' type='image/svg+xml' style='height:50px; width:50px;'></object>";
|
||||
},
|
||||
ParseJson: function (namesconfig) {
|
||||
document.getElementById("content").innerHTML = "";
|
||||
var html = "<div id='nameeditor'><div class='title'>Namenseinträge in den Einstellungen</div>";
|
||||
html += "<table id='nametable' class='settingstable'>";
|
||||
html += "<thead><tr><th width='60'>ID</th><th width='250'>Name</th><th width='65'>Icon</th><th width='150'>Filter Gruppe</th><th width='50'></th></tr></thead>";
|
||||
html += "<tbody>";
|
||||
for (var id in namesconfig) {
|
||||
if (Object.prototype.hasOwnProperty.call(namesconfig, id)) {
|
||||
var nameentry = namesconfig[id];
|
||||
html += "<tr>" +
|
||||
"<td>" + id + "</td>" +
|
||||
"<td>" + nameentry["name"] + "</td>";
|
||||
if (Object.prototype.hasOwnProperty.call(nameentry, "marker.svg")) {
|
||||
html += "<td>" + this.ParseIcon(nameentry["marker.svg"]) + "</td>";
|
||||
} else if (Object.prototype.hasOwnProperty.call(nameentry, "icon")) {
|
||||
html += "<td><img src='" + nameentry["icon"] + "'></td>";
|
||||
} else {
|
||||
html += "<td><img src='../js/leaflet/images/marker-icon.png'></td>";
|
||||
}
|
||||
var gfilter = typeof nameentry.Group === "undefined" ? "no" : nameentry.Group;
|
||||
html += "<td rel='" + gfilter + "'>" + this.filterGropus[gfilter] + "</td>";
|
||||
html += "<td><img src='../icons/general/edit.png' onclick='NamesEditor.Edit(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Delete(this.parentNode.parentNode)' class='pointer'></td>" +
|
||||
"</tr>";
|
||||
}
|
||||
}
|
||||
html += "</tbody>";
|
||||
html += "<tfoot><tr><td></td><td></td><td></td><td></td><td><img src='../icons/general/add.png' onclick='NamesEditor.Add()' class='pointer'> <img src='../icons/general/save.png' onclick='NamesEditor.Save()' class='pointer'></td></tr></tfoot>";
|
||||
html += "</table>";
|
||||
document.getElementById("content").innerHTML = html + "</div>";
|
||||
},
|
||||
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 = "<img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> <object data='" + document.getElementById("markerprev").data + "' type='image/svg+xml' style='height:50px; width:50px;'></object>";
|
||||
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 = "<td>" + id + "</td>" +
|
||||
"<td>" + name + "</td>";
|
||||
if (url === null) {
|
||||
el.innerHTML += "<td><img src='../js/leaflet/images/marker-icon.png'></td>";
|
||||
} else {
|
||||
el.innerHTML += "<td><object data='" + url + "' type='image/svg+xml' style='height:50px; width:50px;'></object></td>";
|
||||
}
|
||||
el.innerHTML += "<td rel='" + gfilter + "'>" + this.filterGropus[gfilter] + "</td>";
|
||||
el.innerHTML += "<td><img src='../icons/general/edit.png' onclick='NamesEditor.Edit(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='NamesEditor.Delete(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
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] || "" };
|
||||
}
|
||||
};
|
330
Lora-Map/resources/admin/js/settings.js
Normal file
330
Lora-Map/resources/admin/js/settings.js
Normal file
@ -0,0 +1,330 @@
|
||||
var Settings = {
|
||||
//public functions
|
||||
Abort: function (el) {
|
||||
el.parentNode.removeChild(el);
|
||||
},
|
||||
AddDensity: function () {
|
||||
var newrow = document.createElement("tr");
|
||||
newrow.innerHTML = "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 195px;'/></td>";
|
||||
newrow.innerHTML += "<td><textarea style='width: 240px;height: 60px;'></textarea></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='Settings.SaveRowdensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
document.getElementById("crowdtable").children[1].appendChild(newrow);
|
||||
},
|
||||
AddFight: function () {
|
||||
var newrow = document.createElement("tr");
|
||||
newrow.innerHTML = "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><textarea style='width: 240px;height: 60px;'></textarea></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='Settings.SaveRowfight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
document.getElementById("fighttable").children[1].appendChild(newrow);
|
||||
},
|
||||
AddSensor: function () {
|
||||
var newrow = document.createElement("tr");
|
||||
newrow.innerHTML = "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 250px;'/></td>";
|
||||
newrow.innerHTML += "<td><input style='width: 145px;'/></td>";
|
||||
newrow.innerHTML += "<td><img src='../icons/general/save.png' onclick='Settings.SaveRowSensor(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
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 = "<td><input style='width: 145px;' value='" + el.children[0].innerText + "'/></td>" +
|
||||
"<td><input style='width: 195px;' value='" + el.children[1].innerText + "'/></td>" +
|
||||
"<td><textarea style='width: 240px;height: 60px;'>" + el.children[2].innerText + "</textarea></td>" +
|
||||
"<td><input style='width: 145px;' value='" + el.children[3].innerText + "'/></td>" +
|
||||
"<td><img src='../icons/general/save.png' onclick='Settings.SaveRowdensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
EditFight: function (el) {
|
||||
el.innerHTML = "<td><input style='width: 145px;' value='" + el.children[0].innerText + "'/></td>" +
|
||||
"<td><textarea style='width: 240px;height: 60px;'>" + el.children[1].innerText + "</textarea></td>" +
|
||||
"<td><input style='width: 145px;' value='" + el.children[2].innerText + "'/></td>" +
|
||||
"<td><input style='width: 145px;' value='" + el.children[3].innerText + "'/></td>" +
|
||||
"<td><img src='../icons/general/save.png' onclick='Settings.SaveRowfight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
EditSensor: function (el) {
|
||||
el.innerHTML = "<td><input style='width: 145px;' value='" + el.children[0].innerText + "'/></td>" +
|
||||
"<td><input style='width: 145px;' value='" + el.children[1].innerText + "'/></td>" +
|
||||
"<td><input style='width: 250px;' value='" + el.children[2].innerText + "'/></td>" +
|
||||
"<td><input style='width: 145px;' value='" + el.children[3].innerText + "'/></td>" +
|
||||
"<td><img src='../icons/general/save.png' onclick='Settings.SaveRowSensor(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
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 = "<div id='settingseditor'><div class='title'>Einstellungen</div>";
|
||||
html += "<div class='startloc'>Startpunkt: <input value='" + jsonsettings.StartPos.lat + "' id='startlat'> Lat, <input value='" + jsonsettings.StartPos.lon + "' id='startlon'> Lon</div>";
|
||||
html += "<div class='wetterwarnings'>CellId's für DWD-Wetterwarnungen: <input value='" + jsonsettings.CellIds.join(";") + "' id='wetterids'> (Trennen durch \";\", <a href='https://www.dwd.de/DE/leistungen/opendata/help/warnungen/cap_warncellids_csv.html'>cap_warncellids_csv</a>)</div>";
|
||||
html += "<div class='gridradius'>Radius für das Grid um den Startpunkt: <input value='" + jsonsettings.GridRadius + "' id='gridrad'>m</div>";
|
||||
html += "<div class='fightdedection'>Fight Dedection Kameras: <br>" + this._renderFightDedection(jsonsettings.FightDedection) + "</div>";
|
||||
html += "<div class='crowddensity'>Crowd Density Kameras: <br>" + this._renderCrowdDensity(jsonsettings.CrwodDensity) + "</div>";
|
||||
html += "<div class='sensorsettings'>Sensors: <br>" + this._renderSensorSettings(jsonsettings.Sensors) + "</div>";
|
||||
html += "<div class='savesettings'><img src='../icons/general/save.png' onclick='Settings.Save()' class='pointer'></div>";
|
||||
document.getElementById("content").innerHTML = html + "</div>";
|
||||
},
|
||||
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("<br>");
|
||||
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("<br>");
|
||||
|
||||
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, "<br>");
|
||||
var coordscheck = coords.split("<br>");
|
||||
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 = "<td>" + el.children[0].children[0].value + "</td>" +
|
||||
"<td>" + el.children[1].children[0].value + "</td>" +
|
||||
"<td>" + coords + "</td>" +
|
||||
"<td>" + el.children[3].children[0].value + "</td>" +
|
||||
"<td><img src='../icons/general/edit.png' onclick='Settings.EditDensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Delete(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
SaveRowfight: function (el) {
|
||||
var coords = el.children[1].children[0].value.replace(/\n/gi, "<br>");
|
||||
var coordscheck = coords.split("<br>");
|
||||
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 = "<td>" + el.children[0].children[0].value + "</td>" +
|
||||
"<td>" + coords + "</td>" +
|
||||
"<td>" + el.children[2].children[0].value + "</td>" +
|
||||
"<td>" + this._filterFloat(el.children[3].children[0].value) + "</td>" +
|
||||
"<td><img src='../icons/general/edit.png' onclick='Settings.EditFight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Delete(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
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 = "<td>" + el.children[0].children[0].value + "</td>" +
|
||||
"<td>" + el.children[1].children[0].value + "</td>" +
|
||||
"<td>" + coords + "</td>" +
|
||||
"<td>" + this._filterFloat(el.children[3].children[0].value) + "</td>" +
|
||||
"<td><img src='../icons/general/edit.png' onclick='Settings.EditSensor(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Delete(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
//private functions
|
||||
_filterFloat: function (value) {
|
||||
if (/^(-|\+)?([0-9]+(\.[0-9]+)?|Infinity)$/.test(value)) {
|
||||
return Number(value);
|
||||
}
|
||||
return NaN;
|
||||
},
|
||||
_renderCrowdDensity: function (json) {
|
||||
var ret = "";
|
||||
ret += "<table id='crowdtable' class='settingstable'>";
|
||||
ret += "<thead><tr><th width='150'>ID</th><th width='200'>Personenanzahl</th><th width='250'>Koordinaten</th><th width='150'>Alias</th><th width='50'></th></tr></thead>";
|
||||
ret += "<tbody>";
|
||||
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 += "<tr>" +
|
||||
"<td>" + id + "</td>" +
|
||||
"<td>" + json[id].Count + "</td>" +
|
||||
"<td>" + coords.join("<br>") + "</td>" +
|
||||
"<td>" + json[id].Alias + "</td>" +
|
||||
"<td><img src='../icons/general/edit.png' onclick='Settings.EditDensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Delete(this.parentNode.parentNode)' class='pointer'></td>" +
|
||||
"</tr>";
|
||||
}
|
||||
ret += "</tbody>";
|
||||
ret += "<tfoot><tr><td></td><td></td><td></td><td></td><td><img src='../icons/general/add.png' onclick='Settings.AddDensity()' class='pointer'></td></tr></tfoot>";
|
||||
ret += "</table>";
|
||||
return ret;
|
||||
},
|
||||
_renderFightDedection: function (json) {
|
||||
var ret = "";
|
||||
ret += "<table id='fighttable' class='settingstable'>";
|
||||
ret += "<thead><tr><th width='150'>ID</th><th width='250'>Koordinaten</th><th width='150'>Alias</th><th width='150'>Alertlimit</th><th width='50'></th></tr></thead>";
|
||||
ret += "<tbody>";
|
||||
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 += "<tr>" +
|
||||
"<td>" + id + "</td>" +
|
||||
"<td>" + coords.join("<br>") + "</td>" +
|
||||
"<td>" + json[id].Alias + "</td>" +
|
||||
"<td>" + json[id].Level + "</td>" +
|
||||
"<td><img src='../icons/general/edit.png' onclick='Settings.EditFight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Delete(this.parentNode.parentNode)' class='pointer'></td>" +
|
||||
"</tr>";
|
||||
}
|
||||
ret += "</tbody>";
|
||||
ret += "<tfoot><tr><td></td><td></td><td></td><td></td><td><img src='../icons/general/add.png' onclick='Settings.AddFight()' class='pointer'></td></tr></tfoot>";
|
||||
ret += "</table>";
|
||||
return ret;
|
||||
},
|
||||
_renderSensorSettings: function (json) {
|
||||
var ret = "";
|
||||
ret += "<table id='sensortable' class='settingstable'>";
|
||||
ret += "<thead><tr><th width='150'>ID</th><th width='150'>Alias</th><th width='250'>Koordinaten</th><th width='150'>Warn above</th><th width='50'></th></tr></thead>";
|
||||
|
||||
ret += "<tbody>";
|
||||
for (var id in json) {
|
||||
ret += "<tr>" +
|
||||
"<td>" + id + "</td>" +
|
||||
"<td>" + json[id].Alias + "</td>" +
|
||||
"<td>" + json[id].Poly.Lat + ";" + json[id].Poly.Lon + "</td>" +
|
||||
"<td>" + json[id].Level + "</td>" +
|
||||
"<td><img src='../icons/general/edit.png' onclick='Settings.EditSensor(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Delete(this.parentNode.parentNode)' class='pointer'></td>" +
|
||||
"</tr>";
|
||||
}
|
||||
ret += "</tbody>";
|
||||
|
||||
ret += "<tfoot><tr><td></td><td></td><td></td><td></td><td><img src='../icons/general/add.png' onclick='Settings.AddSensor()' class='pointer'></td></tr></tfoot>";
|
||||
ret += "</table>";
|
||||
return ret;
|
||||
},
|
||||
};
|
@ -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 {
|
||||
|
@ -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();
|
@ -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("<strong>Besuchermenge:</strong><br>" +
|
||||
"Besucher <strong>(0/" + this._DensityAreas[cameraid].Maximum + ")</strong> Personen<br>" +
|
||||
"<progress value='0' max='" + this._DensityAreas[cameraid].Maximum + "'></progress>");
|
||||
}
|
||||
},
|
||||
_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("<strong>Besuchermenge:</strong><br>" +
|
||||
"Besucher <strong>(" + crowd.DensityCount + "/" + max + ")</strong> Personen<br>" +
|
||||
"<progress value='" + cur + "' max='" + max + "'></progress>").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 = "<b>" + feature.properties.name + "</b>";
|
||||
if (Object.prototype.hasOwnProperty.call(feature.properties, "description")) {
|
||||
text = text + "<br>" + 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("<strong>Besuchermenge:</strong><br>" +
|
||||
"Besucher <strong>(0/" + this._DensityAreas[cameraid].Maximum + ")</strong> Personen<br>" +
|
||||
"<progress value='0' max='" + this._DensityAreas[cameraid].Maximum + "'></progress>");
|
||||
}
|
||||
},
|
||||
_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("<strong>Besuchermenge:</strong><br>" +
|
||||
"Besucher <strong>(" + crowd.DensityCount + "/" + max + ")</strong> Personen<br>" +
|
||||
"<progress value='" + cur + "' max='" + max + "'></progress>").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 = "<b>" + feature.properties.name + "</b>";
|
||||
if (feature.properties.hasOwnProperty("description")) {
|
||||
text = text + "<br>" + 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();
|
@ -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();
|
@ -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 += "<div class='result' onclick='MapObject.JumpTo(" + feature.geometry.coordinates[0][0][1] + "," + feature.geometry.coordinates[0][0][0] + ");'><span class='text'>" +
|
||||
"<span class='title'>" + feature.properties.name + "</span>" +
|
||||
"<span class='desc'>" + (typeof feature.properties.description !== "undefined" ? feature.properties.description : "") + "</span></span>" +
|
||||
"<span class='box' style='background-color: " + feature.properties.fill + "; border-color: " + feature.properties.stroke + "'></span>" +
|
||||
"</div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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 = "<img src=\"" + positionItem['Icon'] + "&marker-bg=hidden" + "\" rel='svg'/>";
|
||||
document.getElementById("overview-icon-id-" + id).innerHTML = "<img src=\"" + positionItem['MenuIcon'] + "\" rel='svg'/>";
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -96,7 +136,7 @@
|
||||
divItem.setAttribute("rel", id);
|
||||
divItem.innerHTML = "<span class=\"color\" id=\"overview-color-id-" + id + "\"></span>";
|
||||
if (positionItem['Icon'] !== null) {
|
||||
divItem.innerHTML += "<span class=\"icon\" id=\"overview-icon-id-" + id + "\"><img src=\"" + positionItem['Icon'] + "&marker-bg=hidden" + "\" rel='svg'/></span>";
|
||||
divItem.innerHTML += "<span class=\"icon\" id=\"overview-icon-id-" + id + "\"><img src=\"" + positionItem['MenuIcon'] + "\" rel='svg'/></span>";
|
||||
} else {
|
||||
divItem.innerHTML += "<span class=\"icon\" id=\"overview-icon-id-" + id + "\"><img src=\"icons/marker/map-marker.png\" /></span>";
|
||||
}
|
||||
@ -119,20 +159,9 @@
|
||||
document.getElementById("pannels_admin").innerHTML = "<a href='/admin/' target='_blank'>Adminpannel</a>";
|
||||
}
|
||||
},
|
||||
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 = "<div class=\"name\">Name: <span class=\"bold\">" + positionItem["Name"] + "</span></div>";
|
||||
html += "<div class=\"batt\"><span class=\"bold\">Batterie:</span> " + positionItem["Battery"] + "V <img src=\"icons/akku/" + positionItem["Batterysimple"] + "-4.png\"></div>";
|
||||
@ -148,7 +177,7 @@
|
||||
html += "<div class=\"lastgps\"><span class=\"bold\">Letzter Wert:</span> Vor: " + FunctionsObject.TimeCalculation(positionItem["Lastgpspostime"], "difftext") + "</div>";
|
||||
html += "<div class=\"update\"><span class=\"bold\">Update:</span> " + FunctionsObject.TimeCalculation(positionItem["Recievedtime"], "str") + "<br><span class=\"bold\">Vor:</span> " + FunctionsObject.TimeCalculation(positionItem["Recievedtime"], "difftext") + "</div>";
|
||||
html += "<div><span class=\"bold\">RSSI:</span> " + positionItem["Rssi"] + ", <span class=\"bold\">SNR:</span> " + positionItem["Snr"] + "</div>";
|
||||
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 += "<div class='alerts'><span class=\"bold\">Alerts:</span>";
|
||||
@ -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 += " <b>Bis:</b> in " + FunctionsObject.TimeCalculation(walert.To, "difftextn") + "</span>" +
|
||||
"</div>";
|
||||
@ -197,25 +226,5 @@
|
||||
document.getElementById("pannels_weather").innerHTML = "<h1>Keine Gefahren</h1>";
|
||||
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 += "<div class='result' onclick='MapObject.JumpTo(" + feature.geometry.coordinates[0][0][1] + "," + feature.geometry.coordinates[0][0][0]+");'><span class='text'>" +
|
||||
"<span class='title'>" + feature.properties.name + "</span>" +
|
||||
"<span class='desc'>" + (typeof feature.properties.description !== "undefined" ? feature.properties.description : "") + "</span></span>" +
|
||||
"<span class='box' style='background-color: " + feature.properties.fill + "; border-color: " + feature.properties.stroke + "'></span>" +
|
||||
"</div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
document.getElementById("search_results").innerHTML = html;
|
||||
}
|
||||
}.Start();
|
@ -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 = "<div class='camera'>";
|
||||
cameratext += "<span class='name'>" + cameraid + "</span>";
|
||||
@ -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 = "<div class='camera'>";
|
||||
densytext += "<span class='name'>" + this._DensitySettings[densyid].Alias + "</span>";
|
||||
@ -34,8 +44,5 @@
|
||||
}
|
||||
}
|
||||
document.getElementById("crwoddensy").innerHTML = densystext;
|
||||
},
|
||||
_ParseAJAXSettings: function (json) {
|
||||
this._DensitySettings = json["DensityArea"];
|
||||
}
|
||||
}.Start();
|
BIN
doc/Details.pdn
Normal file
BIN
doc/Details.pdn
Normal file
Binary file not shown.
BIN
doc/Filter-Select.png
Normal file
BIN
doc/Filter-Select.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
99
doc/Manual.md
Normal file
99
doc/Manual.md
Normal file
@ -0,0 +1,99 @@
|
||||
# Lora-Map
|
||||
Lora-Map ist eine Karte die GPS-Positionen von Geräten anzeigt.
|
||||

|
||||
|
||||
## Bedienung
|
||||
In diesem abschnitt findet sich eine Bedienungsnleitung über alle Funktionen der Karte.
|
||||
|
||||
### 1. Zoombuttons
|
||||

|
||||
Diese Knöpfe werden zum Steuern der Karte verwendet. Dabei kann mit `+` in die Karte hineingezoomt werden
|
||||
und mit `-` aus der Karte herraus.
|
||||
|
||||
### 2. Tracker
|
||||

|
||||
Über diesen Schalter lassen sich Informationen über alle, sowie über einzelne Tracker abrufen.
|
||||
|
||||
#### 2.1 Gesamtliste
|
||||

|
||||
Hier wird eine Übersicht über alle aktiven Tracker angezeigt. Diese können angeklickt werden um Details zu
|
||||
diesen zu sehen (siehe Abschnitt 2.2).
|
||||
|
||||
##### 2.1.1 Batteriestatus
|
||||
Der horizontale Balken in `Grün`, `Gelb` oder `Rot` zeigt den Akkuzustand schnell erkenntlich an. Grüne
|
||||
Tracker sind voll, Gelbe etwa halbvoll und Rote sollen geladen werden.
|
||||
|
||||
##### 2.1.2 Icon
|
||||
Hier wird das Icon des Trackers dargestellt.
|
||||
|
||||
##### 2.1.3 Name
|
||||
Hier erscheint der Eingetragene `Name` des Trackers. Dies kann ein Funkrufname oder auch ein anderes Kürzel
|
||||
sein. Die Anzahl der Zeichen ist begrenzt, da dieser Name auch auf der Karte über den Symbolen erscheint.
|
||||
|
||||
##### 2.1.4 Akkusymbol
|
||||
Hier wird in einem 5 Stufensystem der Ladezustand des Trackers angezeigt. Jede Stufe entpricht etwa 3
|
||||
Stunden und 10 Minuten (Gesamtlaufzeit etwa 16 Stunden.)
|
||||
|
||||
##### 2.1.5 GPS-Status
|
||||
Hier wird dargestellt ob der Tracker bei seinem letzten Empfang ein gültiges GPS-Signal gesendet hat, also
|
||||
selbst Empfang hatte. In Gebäuden oder unter Brücken kann es passieren das der Tracker keinen Empfang
|
||||
mehr hat. Ebenso ist der Empfang nach dem Einsachalten nicht sofort verfügbar.
|
||||
|
||||
##### 2.1.6 Letzer Signalempfang
|
||||
In dieser Zeile wird die Zeitspanne seit dem letzten Signalempfang über Funk vom Tracker angezeigt. Somit
|
||||
ist ersichtlich wie Aktuell die genannte Posiotion auf der Karte ist.
|
||||
|
||||
#### 2.2 Tracker-Detail
|
||||

|
||||
Diese Ansicht zeigt Details zu einem Tracker an, sobald dieser über die Karte oder die Gesamtliste
|
||||
ausgewählt wurde. Sollte bei einem Tracker der Alarmknopf gedrückt werden, wird diese Ansicht ebenfalls
|
||||
geöffnet.
|
||||
|
||||
##### 2.2.1 Name
|
||||
Siehe 2.1.3.
|
||||
|
||||
##### 2.2.2 Akkusymbol
|
||||
Siehe 2.1.4. Zusätzlich wird die Spannung in Volt angezeigt.
|
||||
|
||||
##### 2.2.3 GPS-Status
|
||||
Siehe 2.1.5.
|
||||
|
||||
##### 2.2.4 MGRS-Koordinaten
|
||||
Koordinaten des Trackers im UTM-Referenzsystem. Hier wird der zuletzt empfangene Wert angezeigt.
|
||||
|
||||
##### 2.2.5 Höhe
|
||||
Die Höhe der Position des Trackers in Meter über NN.
|
||||
|
||||
##### 2.2.6 HDOP
|
||||
Die [ungenauigkeit](https://de.wikipedia.org/wiki/Dilution_of_Precision) des GPS-Signals. Achtung, dieser
|
||||
Wert ist keine Angabe in Metern. Gute Werte sind kleiner 1,2
|
||||
|
||||
##### 2.2.7 GPS-Koordinaten
|
||||
Die MGRS-Koordinaten umgerechnet in Dezimalgraden.
|
||||
|
||||
##### 2.2.8 Letzter GPS Wert
|
||||
Diese Angabe bezieht sich auf die letzten korrekt Empfangenen Koordinaten, somit kann festgestellt werden
|
||||
ob ein Tracker GPS-Empfang hat. Ein Tracker kann unter umständen Empfangen werden, aber z.B. innerhalb
|
||||
eines Gebäudes sein und selbst keinen GPS-Empfang haben. Dort wird dann angezeigt wann er selbst zuletzt
|
||||
Empfang hatte.
|
||||
|
||||
##### 2.2.9 Update
|
||||
Zeitpunkt und Zeitraum des zuletzt empfangen Funksignals.
|
||||
|
||||
##### 2.2.10 Empfangstärke
|
||||
RSSI (Received signal strength indication) und SNR (Signal-to-noise ratio) geben die Qualität der
|
||||
Funkverbindung zum Tracker an. Je größer die Werte desto besser.
|
||||
|
||||
##### 2.2.11 Alerts
|
||||
Hier werden die letzten 10 Zeitpunkte der Alarmmeldungen angezeigt.
|
||||
|
||||
### 3. Filter
|
||||

|
||||
Über diesen Schalter lassen sich die Filtereinstellungen aufrufen.
|
||||
|
||||
### 3.1 Filter-Auswahl
|
||||

|
||||
In der Liste können die Gruppen ausgewählt werden, welche auf der Karte dargestellt werden sollen. Es
|
||||
können mehrere Gruppen gleichzeit oder auch garkeine ausgewält werden (dann werden alle dargestellt).
|
||||
|
||||
### 3.2 Filter-Details
|
@ -1,39 +0,0 @@
|
||||
# Lora-Map
|
||||
Lora-Map ist eine Karte die GPS-Positionen von Geräten anzeigt.
|
||||

|
||||
|
||||
## Bedienung
|
||||
In diesem abschnitt findet sich eine Bedienungsnleitung über alle Funktionen der Karte.
|
||||
|
||||
### 1. Zoombuttons
|
||||

|
||||
Diese Knöpfe werden zum Steuern der Karte verwendet. Dabei kann mit `+` in die Karte hineingezoomt werden und mit `-` aus der Karte herraus.
|
||||
|
||||
### 2. Tracker
|
||||

|
||||
Über diesen Schalter lassen sich Informationen über alle, sowie über einzelne Tracker abrufen.
|
||||
|
||||
#### 2.1 Gesamtliste
|
||||

|
||||
Hier wird eine Übersicht über alle aktiven Tracker angezeigt. Diese können angeklickt werden um Details zu diesen zu sehen [(siehe Abschnitt 2.2)][id_2_2].
|
||||
|
||||
##### 2.1.1 Batteriestatus
|
||||
Der horizontale Balken in `Grün`, `Gelb` oder `Rot` zeigt den Akkuzustand schnell erkenntlich an. Grüne Tracker sind voll, Gelbe etwa halbvoll und Rote sollen geladen werden.
|
||||
|
||||
##### 2.1.2 Icon
|
||||
Hier wird das Icon des Trackers dargestellt.
|
||||
|
||||
##### 2.1.3 Name
|
||||
Hier erscheint der Eingetragene `Name` des Trackers. Dies kann ein Funkrufname oder auch ein anderes Kürzel sein. Die Anzahl der Zeichen ist begrenzt, da dieser Name auch auf der Karte über den Symbolen erscheint.
|
||||
|
||||
##### 2.1.4 Akkusymbol
|
||||
Hier wird in einem 5 Stufensystem der Ladezustand des Trackers angezeigt. Jede Stufe entpricht etwa 3 Stunden und 10 Minuten (Gesamtlaufzeit etwa 16 Stunden.)
|
||||
|
||||
##### 2.1.5 GPS-Status
|
||||
Hier wird dargestellt ob der Tracker bei seinem letzten Empfang ein gültiges GPS-Signal gesendet hat, also selbst Empfang hatte. In Gebäuden oder unter Brücken kann es passieren das der Tracker keinen Empfang mehr hat.
|
||||
Ebenso ist der Empfang nach dem Einsachalten nicht sofort verfügbar.
|
||||
|
||||
##### 2.1.6 Letzer Signalempfang
|
||||
In dieser Zeile wird die Zeitspanne seit dem letzten Signalempfang über Funk vom Tracker angezeigt. Somit ist ersichtlich wie Aktuell die genannte Posiotion auf der Karte ist.
|
||||
|
||||
#### 2.2 Tracker-Detail
|
BIN
doc/Symbol-Filter.png
Normal file
BIN
doc/Symbol-Filter.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
BIN
doc/Trackerdetail.pdn
Normal file
BIN
doc/Trackerdetail.pdn
Normal file
Binary file not shown.
BIN
doc/Trackerdetail.png
Normal file
BIN
doc/Trackerdetail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
312
map-swagger.yml
Normal file
312
map-swagger.yml
Normal file
@ -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: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> 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.
|
Loading…
Reference in New Issue
Block a user