Merge branch 'v1.2.9' into 'master'

[1.2.9] The PüMa Release

See merge request monica/lora-map/lora-map!2
This commit is contained in:
philip.schell 2019-08-30 15:53:51 +02:00
commit f192cc7b52
27 changed files with 1862 additions and 855 deletions

View File

@ -1,5 +1,23 @@
# Changelogs
## 1.2.9
### New Features
* Add setting model to code
* #19 grid automatisch generieren
* #24 Add information about weather/warning
* #28 Fightdedection Plygon on Map
* #27 Draw Camera-Desity bock on map
* #16 filter nach kategorien/tracker einbauen
* #15 suche nach ständen einbauen
### Bugfixes
* Add Correct Dispose Handling
* TimeCalculation now handle negative values correct
### Changes
* Refactoring of all JS
* Make only one request per second instead of four per AJAX
* Refactoring adminpannel and add settings.json
* New function in TimeCalculation, so you can not have negative Timespans
## 1.2.8
### New Features
* Implement #12 Make icon transparent if there is no data update

View File

@ -0,0 +1,62 @@
using System;
using System.IO;
using System.Net;
using BlubbFish.Utils;
using LitJson;
namespace Fraunhofer.Fit.IoT.LoraMap.Lib {
public class WebRequests {
private static readonly Object getLock = new Object();
public JsonData GetJson(String url) {
String text = null;
for(Int32 i = 0; i < 3; i++) {
try {
text = this.GetString(url);
break;
} catch(Exception e) {
Helper.WriteError(e.Message);
if(i == 2) {
throw;
}
System.Threading.Thread.Sleep(30000);
}
}
if(text == null) {
return new JsonData();
}
try {
return JsonMapper.ToObject(text);
} catch(Exception) {
return new JsonData();
}
}
private String GetString(String url, Boolean withoutput = true) {
String ret = null;
lock(getLock) {
HttpWebRequest request = WebRequest.CreateHttp(url);
request.Timeout = 10000;
//request.Headers.Add(HttpRequestHeader.Authorization, this.auth);
try {
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
if(response.StatusCode == HttpStatusCode.Unauthorized) {
Console.Error.WriteLine("Benutzer oder Passwort falsch!");
throw new Exception("Benutzer oder Passwort falsch!");
}
if(withoutput) {
StreamReader reader = new StreamReader(response.GetResponseStream());
ret = reader.ReadToEnd();
}
}
} catch(Exception e) {
//Helper.WriteError("Konnte keine Verbindung zum Razzbery Server herstellen. Resource: \"" + this.server + v + "\" Fehler: " + e.Message);
//return null;
throw new Exception("Konnte keine Verbindung zum Server herstellen: " + e.Message);
}
}
return ret;
}
}
}

View File

@ -45,13 +45,17 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Lib\WebRequests.cs" />
<Compile Include="Model\Admin\AdminModel.cs" />
<Compile Include="Model\Admin\AdminSession.cs" />
<Compile Include="Model\Camera.cs" />
<Compile Include="Model\Crowd.cs" />
<Compile Include="Model\Fight.cs" />
<Compile Include="Model\Marker.cs" />
<Compile Include="Model\AlarmItem.cs" />
<Compile Include="Model\Settings.cs" />
<Compile Include="Model\UTMData.cs" />
<Compile Include="Model\WeatherWarnings.cs" />
<Compile Include="Server.cs" />
<Compile Include="Model\PositionItem.cs" />
<Compile Include="Program.cs" />
@ -98,12 +102,24 @@
<Content Include="resources\css\icons\failtile.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="resources\css\icons\filter.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="resources\css\icons\information.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="resources\css\icons\placeholder.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="resources\css\icons\search.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="resources\css\icons\storm-ac.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="resources\css\icons\storm-in.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="resources\icons\akku\0-4.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -236,8 +252,6 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Folder Include="Helper\" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,157 +1,131 @@
using System;
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);
public event AdminEvent NamesUpdate;
private readonly Dictionary<Int64, AdminSession> session = new Dictionary<Int64, AdminSession>();
private readonly Dictionary<String, String> settings;
public AdminModel(Dictionary<String, String> settings) {
this.settings = settings;
if(!settings.ContainsKey("admin_user") || !settings.ContainsKey("admin_pass")) {
Helper.WriteError("Kann die Einstellungen [webserver] admin_user und admin_pass nicht laden!");
throw new FileNotFoundException("Kann die Einstellungen [webserver] admin_user und admin_pass nicht laden!");
}
}
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/get_json_")) {
return this.SendJson(cont);
}
if(cont.Request.Url.PathAndQuery.StartsWith("/admin/set_json_")) {
return this.GetJson(cont);
}
return Webserver.SendFileResponse(cont);
}
private Boolean GetJson(HttpListenerContext cont) {
if(cont.Request.Url.PathAndQuery == "/admin/set_json_names") {
StreamReader reader = new StreamReader(cont.Request.InputStream, cont.Request.ContentEncoding);
String rawData = reader.ReadToEnd();
cont.Request.InputStream.Close();
reader.Close();
try {
JsonMapper.ToObject(rawData);
} catch(Exception) {
Helper.WriteError("501 - Error recieving names.json " + cont.Request.Url.PathAndQuery);
cont.Response.StatusCode = 501;
return false;
}
File.WriteAllText("json/names.json", rawData);
Console.WriteLine("200 - Post names.json " + cont.Request.Url.PathAndQuery);
this.NamesUpdate?.Invoke(this, new EventArgs());
return true;
} else if(cont.Request.Url.PathAndQuery == "/admin/set_json_geo") {
StreamReader reader = new StreamReader(cont.Request.InputStream, cont.Request.ContentEncoding);
String rawData = reader.ReadToEnd();
cont.Request.InputStream.Close();
reader.Close();
try {
JsonMapper.ToObject(rawData);
} catch(Exception) {
Helper.WriteError("501 - Error recieving geo.json " + cont.Request.Url.PathAndQuery);
cont.Response.StatusCode = 501;
return false;
}
File.WriteAllText("json/geo.json", rawData);
Console.WriteLine("200 - Post geo.json " + cont.Request.Url.PathAndQuery);
this.NamesUpdate?.Invoke(this, new EventArgs());
return true;
}
return false;
}
private Boolean SendJson(HttpListenerContext cont) {
if(cont.Request.Url.PathAndQuery == "/admin/get_json_names") {
String file = File.ReadAllText("json/names.json");
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);
return true;
} else if(cont.Request.Url.PathAndQuery == "/admin/get_json_geo") {
String file = File.ReadAllText("json/geo.json");
Byte[] buf = Encoding.UTF8.GetBytes(file);
cont.Response.ContentLength64 = buf.Length;
cont.Response.OutputStream.Write(buf, 0, buf.Length);
Console.WriteLine("200 - Send geo.json " + cont.Request.Url.PathAndQuery);
return true;
}
Helper.WriteError("404 - Section in get_json not found " + cont.Request.Url.PathAndQuery + "!");
cont.Response.StatusCode = 404;
return false;
}
private Boolean Login(HttpListenerContext cont) {
Dictionary<String, String> POST = Webserver.GetPostParams(cont.Request);
if(POST.ContainsKey("user") && POST["user"] == this.settings["admin_user"] && POST.ContainsKey("pass") && POST["pass"] == this.settings["admin_pass"]) {
Int64 sessionid = 0;
while(true) {
sessionid = AdminSession.GetRandomSessionid();
if(!this.session.ContainsKey(sessionid)) {
break;
}
}
if(cont.Request.Cookies["loramapsession"] != null) {
if(Int64.TryParse(cont.Request.Cookies["loramapsession"].Value, out Int64 cookiesessionid)) {
if(this.session.ContainsKey(cookiesessionid)) {
if(!this.session[sessionid].IsLoggedin) {
sessionid = cookiesessionid;
}
}
}
}
if(!this.session.ContainsKey(sessionid)) {
this.session.Add(sessionid, new AdminSession());
}
this.session[sessionid].IsLoggedin = true;
cont.Response.AppendCookie(new Cookie("loramapsession", sessionid.ToString()) {
Expires = DateTime.Now.AddYears(1)
});
cont.Response.AddHeader("Location", "/admin");
cont.Response.StatusCode = 307;
Console.WriteLine("200 - Login OK! " + cont.Request.Url.PathAndQuery);
return true;
}
cont.Response.AddHeader("Location", "/admin/login.html");
cont.Response.StatusCode = 307;
Helper.WriteError("307 - Login WRONG! " + cont.Request.Url.PathAndQuery);
return false;
}
private Boolean CheckAuth(HttpListenerContext cont) {
#if DEBUG
return true;
#endif
if(cont.Request.Url.PathAndQuery.StartsWith("/admin/login.html")) {
return true;
} else {
if(cont.Request.Cookies["loramapsession"] != null) {
if(Int64.TryParse(cont.Request.Cookies["loramapsession"].Value, out Int64 sessionid)) {
if(this.session.ContainsKey(sessionid)) {
return this.session[sessionid].IsLoggedin;
}
}
}
cont.Response.StatusCode = 403;
Helper.WriteError("403 - " + cont.Request.Url.PathAndQuery);
}
return false;
}
}
}
using System;
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);
public event AdminEvent NamesUpdate;
public event AdminEvent GeoUpdate;
public event AdminEvent SettingsUpdate;
private readonly Dictionary<Int64, AdminSession> session = new Dictionary<Int64, AdminSession>();
private readonly Dictionary<String, String> settings;
public AdminModel(Dictionary<String, String> settings) {
this.settings = settings;
if(!settings.ContainsKey("admin_user") || !settings.ContainsKey("admin_pass")) {
Helper.WriteError("Kann die Einstellungen [webserver] admin_user und admin_pass nicht laden!");
throw new FileNotFoundException("Kann die Einstellungen [webserver] admin_user und admin_pass nicht laden!");
}
}
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);
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) {
StreamReader reader = new StreamReader(cont.Request.InputStream, cont.Request.ContentEncoding);
String rawData = reader.ReadToEnd();
cont.Request.InputStream.Close();
reader.Close();
try {
JsonMapper.ToObject(rawData);
} catch (Exception) {
Helper.WriteError("501 - Error recieving " + filename + ", no valid json " + cont.Request.Url.PathAndQuery);
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);
return true;
}
private Boolean Login(HttpListenerContext cont) {
Dictionary<String, String> POST = Webserver.GetPostParams(cont.Request);
if(POST.ContainsKey("user") && POST["user"] == this.settings["admin_user"] && POST.ContainsKey("pass") && POST["pass"] == this.settings["admin_pass"]) {
Int64 sessionid = 0;
while(true) {
sessionid = AdminSession.GetRandomSessionid();
if(!this.session.ContainsKey(sessionid)) {
break;
}
}
if(cont.Request.Cookies["loramapsession"] != null) {
if(Int64.TryParse(cont.Request.Cookies["loramapsession"].Value, out Int64 cookiesessionid)) {
if(this.session.ContainsKey(cookiesessionid)) {
if(!this.session[sessionid].IsLoggedin) {
sessionid = cookiesessionid;
}
}
}
}
if(!this.session.ContainsKey(sessionid)) {
this.session.Add(sessionid, new AdminSession());
}
this.session[sessionid].IsLoggedin = true;
cont.Response.AppendCookie(new Cookie("loramapsession", sessionid.ToString()) {
Expires = DateTime.Now.AddYears(1)
});
cont.Response.AddHeader("Location", "/admin");
cont.Response.StatusCode = 307;
Console.WriteLine("200 - Login OK! " + cont.Request.Url.PathAndQuery);
return true;
}
cont.Response.AddHeader("Location", "/admin/login.html");
cont.Response.StatusCode = 307;
Helper.WriteError("307 - Login WRONG! " + cont.Request.Url.PathAndQuery);
return false;
}
private Boolean CheckAuth(HttpListenerContext cont) {
#if DEBUG
return true;
#endif
if(cont.Request.Url.PathAndQuery.StartsWith("/admin/login.html")) {
return true;
} else {
if(cont.Request.Cookies["loramapsession"] != null) {
if(Int64.TryParse(cont.Request.Cookies["loramapsession"].Value, out Int64 sessionid)) {
if(this.session.ContainsKey(sessionid)) {
return this.session[sessionid].IsLoggedin;
}
}
}
cont.Response.StatusCode = 403;
Helper.WriteError("403 - " + cont.Request.Url.PathAndQuery);
}
return false;
}
}
}

View File

@ -1,63 +1,51 @@
using LitJson;
using System;
using System.Globalization;
namespace Fraunhofer.Fit.IoT.LoraMap.Model
{
public class Crowd
{
public Int32 DensityCount { get; private set; }
public DateTime LastUpdate { get; private set; }
public Double AverageFlowMagnitude { get; private set; }
public Double AverageFlowDirection { get; private set; }
public Double Cofidence { get; private set; }
public String Situation { get; private set; }
public Crowd(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 &&
json.ContainsKey("type_module") && json["type_module"].IsString && json["type_module"].ToString() == "crowd_density_local" &&
json.ContainsKey("density_count") && json["density_count"].IsInt &&
json.ContainsKey("timestamp1") && json["timestamp1"].IsString;
public static Boolean CheckJsonFlow(JsonData json) => json.ContainsKey("camera_ids") && json["camera_ids"].IsArray && json["camera_ids"].Count == 1 &&
json.ContainsKey("average_flow_magnitude") && json["average_flow_magnitude"].IsArray &&
json.ContainsKey("type_module") && json["type_module"].IsString && json["type_module"].ToString() == "flow" &&
json.ContainsKey("average_flow_direction") && json["average_flow_direction"].IsArray &&
json.ContainsKey("timestamp") && json["timestamp"].IsString;
public static Boolean CheckJsonFightingDetection(JsonData json) => json.ContainsKey("camera_ids") && json["camera_ids"].IsArray && json["camera_ids"].Count == 1 &&
json.ContainsKey("confidence") && json["confidence"].IsDouble &&
json.ContainsKey("type_module") && json["type_module"].IsString && json["type_module"].ToString() == "fighting_detection" &&
json.ContainsKey("situation") && json["situation"].IsString &&
json.ContainsKey("timestamp") && json["timestamp"].IsString;
public static String GetId(JsonData json) => (String)json["camera_ids"][0];
public void Update(JsonData json) {
if(CheckJsonCrowdDensityLocal(json)) {
this.DensityCount = (Int32)json["density_count"];
if (DateTime.TryParse((String)json["timestamp1"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) {
this.LastUpdate = updatetime.ToUniversalTime();
}
} else if(CheckJsonFlow(json)) {
if (json["average_flow_magnitude"].Count == 1) {
this.AverageFlowMagnitude = (Double)json["average_flow_magnitude"][0];
}
if (json["average_flow_direction"].Count == 1) {
this.AverageFlowDirection = (Double)json["average_flow_direction"][0];
}
if (DateTime.TryParse((String)json["timestamp"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) {
this.LastUpdate = updatetime.ToUniversalTime();
}
} else if(CheckJsonFightingDetection(json)) {
this.Cofidence = (Double)json["confidence"];
this.Situation = (String)json["situation"];
if (DateTime.TryParse((String)json["timestamp"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) {
this.LastUpdate = updatetime.ToUniversalTime();
}
}
}
}
}
using LitJson;
using System;
using System.Globalization;
namespace Fraunhofer.Fit.IoT.LoraMap.Model
{
public class Crowd
{
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 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 &&
json.ContainsKey("type_module") && json["type_module"].IsString && json["type_module"].ToString() == "crowd_density_local" &&
json.ContainsKey("density_count") && json["density_count"].IsInt &&
json.ContainsKey("timestamp_1") && json["timestamp_1"].IsString;
public static Boolean CheckJsonFlow(JsonData json) => json.ContainsKey("camera_ids") && json["camera_ids"].IsArray && json["camera_ids"].Count == 1 &&
json.ContainsKey("average_flow_magnitude") && json["average_flow_magnitude"].IsArray &&
json.ContainsKey("type_module") && json["type_module"].IsString && json["type_module"].ToString() == "flow" &&
json.ContainsKey("average_flow_direction") && json["average_flow_direction"].IsArray &&
json.ContainsKey("timestamp") && json["timestamp"].IsString;
public static String GetId(JsonData json) => (String)json["camera_ids"][0];
public void Update(JsonData json) {
if(CheckJsonCrowdDensityLocal(json)) {
this.DensityCount = (Int32)json["density_count"];
if (DateTime.TryParse((String)json["timestamp_1"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) {
this.TimeStamp = updatetime.ToUniversalTime();
}
} else if(CheckJsonFlow(json)) {
if (json["average_flow_magnitude"].Count == 1) {
this.AverageFlowMagnitude = (Double)json["average_flow_magnitude"][0];
}
if (json["average_flow_direction"].Count == 1) {
this.AverageFlowDirection = (Double)json["average_flow_direction"][0];
}
if (DateTime.TryParse((String)json["timestamp"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) {
this.TimeStamp = updatetime.ToUniversalTime();
}
}
this.LastUpdate = DateTime.UtcNow;
}
}
}

35
Lora-Map/Model/Fight.cs Normal file
View File

@ -0,0 +1,35 @@
using LitJson;
using System;
using System.Globalization;
namespace Fraunhofer.Fit.IoT.LoraMap.Model {
public class Fight {
public Fight(JsonData json) => this.Update(json);
public DateTime LastUpdate { get; private set; }
public DateTime TimeStamp { get; private set; }
public String Situation { get; private set; }
public Double FightProbability { get; private set; }
public static Boolean CheckJsonFightingDetection(JsonData json) => json.ContainsKey("camera_ids") && json["camera_ids"].IsArray && json["camera_ids"].Count == 1 &&
json.ContainsKey("confidence") && json["confidence"].IsString &&
json.ContainsKey("type_module") && json["type_module"].IsString && json["type_module"].ToString() == "fighting_detection" &&
json.ContainsKey("situation") && json["situation"].IsString &&
json.ContainsKey("timestamp") && json["timestamp"].IsString;
public static String GetId(JsonData json) => (String)json["camera_ids"][0];
public void Update(JsonData json) {
if (CheckJsonFightingDetection(json)) {
if (Double.TryParse((String)json["confidence"], NumberStyles.Float, CultureInfo.InvariantCulture, out Double cofidence)) {
this.FightProbability = cofidence;
}
this.Situation = (String)json["situation"];
if (DateTime.TryParse((String)json["timestamp"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) {
this.TimeStamp = updatetime.ToUniversalTime();
}
this.LastUpdate = DateTime.UtcNow;
}
}
}
}

View File

@ -37,7 +37,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model
}
}
}
ret += (ret.Contains("?")) ? "&name=" + name : "?name=" + name;
ret += ret.Contains("?") ? "&name=" + name : "?name=" + name;
return ret;
}

View File

@ -19,8 +19,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 Group { get; private set; }
public PositionItem(JsonData json, JsonData marker) {
this.Update(json);
@ -29,21 +28,13 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model {
public void UpdateMarker(JsonData marker, String id) {
if(marker.ContainsKey(id)) {
if(marker[id].ContainsKey("name") && marker[id]["name"].IsString) {
this.Name = (String)marker[id]["name"];
} else {
this.Name = id;
}
if(marker[id].ContainsKey("marker.svg") && marker[id]["marker.svg"].IsObject) {
this.Icon = Marker.ParseMarkerConfig(marker[id]["marker.svg"], this.Name);
} else if(marker[id].ContainsKey("icon") && marker[id]["icon"].IsString) {
this.Icon = (String)marker[id]["icon"];
} else {
this.Icon = null;
}
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;
this.Group = marker[id].ContainsKey("Group") && marker[id]["Group"].IsString ? (String)marker[id]["Group"] : "no";
} else {
this.Name = id;
this.Icon = null;
this.Group = null;
}
}
public static Boolean CheckJson(JsonData json) => json.ContainsKey("Rssi") && json["Rssi"].IsDouble
@ -71,17 +62,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model {
}
this.Recievedtime = DateTime.UtcNow;
this.Battery = Math.Round((Double)json["BatteryLevel"], 2);
if(this.Battery < 3.44) {
this.Batterysimple = 0;
} else if(this.Battery < 3.53) {
this.Batterysimple = 1;
} else if(this.Battery < 3.6525) {
this.Batterysimple = 2;
} else if(this.Battery < 3.8825) {
this.Batterysimple = 3;
} else {
this.Batterysimple = 4;
}
this.Batterysimple = this.Battery < 3.44 ? 0 : this.Battery < 3.53 ? 1 : this.Battery < 3.6525 ? 2 : this.Battery < 3.8825 ? 3 : 4;
this.Latitude = (Double)json["Gps"]["Latitude"];
this.Longitude = (Double)json["Gps"]["Longitude"];
this.Fix = (Boolean)json["Gps"]["Fix"];

170
Lora-Map/Model/Settings.cs Normal file
View File

@ -0,0 +1,170 @@
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>();
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, List<List<Double>>> FightDedection { get; private set; }
public Dictionary<String, Density> DensityArea { get; private set; }
public Settings() => this.ParseJson();
public void AdminModelUpdateSettings(Object sender, EventArgs e) => this.ParseJson();
private void ParseJson() {
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"];
} else {
this.Startloclat = 0;
this.Startloclon = 0;
}
this.weatherCellIDs.Clear();
if (json.ContainsKey("CellIds") && json["CellIds"].IsArray && json["CellIds"].Count > 0) {
foreach (JsonData item in json["CellIds"]) {
if(Int32.TryParse(item.ToString(), out Int32 cellid)) {
this.weatherCellIDs.Add(cellid);
}
}
}
if(json.ContainsKey("FightDedection") && json["FightDedection"].IsObject) {
Dictionary<String, List<List<Double>>> fight = new Dictionary<String, List<List<Double>>>();
foreach (KeyValuePair<String, JsonData> entry in json["FightDedection"]) {
List<List<Double>> poly = new List<List<Double>>();
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) {
coords.Add((Double)coord["Lat"]);
coords.Add((Double)coord["Lon"]);
}
poly.Add(coords);
}
}
fight.Add(entry.Key, poly);
}
this.FightDedection = fight;
}
if (json.ContainsKey("CrwodDensity") && json["CrwodDensity"].IsObject) {
Dictionary<String, Density> densitys = new Dictionary<String, Density>();
foreach (KeyValuePair<String, JsonData> entry in json["CrwodDensity"]) {
Density density = new Density();
density.Polygon = new List<List<Double>>();
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) {
coords.Add((Double)coord["Lat"]);
coords.Add((Double)coord["Lon"]);
}
density.Polygon.Add(coords);
}
}
if(entry.Value.ContainsKey("Count") && (entry.Value["Count"].IsInt || entry.Value["Count"].IsDouble)) {
density.Maximum = (Int32)entry.Value["Count"];
}
densitys.Add(entry.Key, density);
}
this.DensityArea = densitys;
}
this.gridradius = json.ContainsKey("GridRadius") && json["GridRadius"].IsInt && this.Startloclat != 0 && this.Startloclon != 0 ? (Int32)json["GridRadius"] : 0;
this.GenerateGrid();
}
private void GenerateGrid() {
if(this.Startloclat == 0 || this.Startloclon == 0 || this.gridradius == 0) {
return;
}
MilitaryGridReferenceSystem start = new Coordinate(this.Startloclat, this.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);
this.Grid = new Dictionary<String, List<Dictionary<String, List<Double>>>> {
{ "Major", new List<Dictionary<String, List<Double>>>() },
{ "Minor", new List<Dictionary<String, List<Double>>>() }
};
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>> {
{ "from", new List<Double> {
TopLeft.Latitude.DecimalDegree,
TopLeft.Longitude.DecimalDegree
}
},
{ "to", new List<Double> {
BottomLeft.Latitude.DecimalDegree,
BottomLeft.Longitude.DecimalDegree
}
}
});
} else {
this.Grid["Minor"].Add(new Dictionary<String, List<Double>> {
{ "from", new List<Double> {
TopLeft.Latitude.DecimalDegree,
TopLeft.Longitude.DecimalDegree
}
},
{ "to", new List<Double> {
BottomLeft.Latitude.DecimalDegree,
BottomLeft.Longitude.DecimalDegree
}
}
});
}
}
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>> {
{ "from", new List<Double> {
BottomLeft.Latitude.DecimalDegree,
BottomLeft.Longitude.DecimalDegree
}
},
{ "to", new List<Double> {
BottomRight.Latitude.DecimalDegree,
BottomRight.Longitude.DecimalDegree
}
}
});
} else {
this.Grid["Minor"].Add(new Dictionary<String, List<Double>> {
{ "from", new List<Double> {
BottomLeft.Latitude.DecimalDegree,
BottomLeft.Longitude.DecimalDegree
}
},
{ "to", new List<Double> {
BottomRight.Latitude.DecimalDegree,
BottomRight.Longitude.DecimalDegree
}
}
});
}
}
}
public List<Int32> GetWeatherCellIds() => this.weatherCellIDs;
public struct Density {
public List<List<Double>> Polygon { get; set; }
public Int32 Maximum { get; set; }
}
}
}

View File

@ -0,0 +1,166 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Fraunhofer.Fit.IoT.LoraMap.Lib;
using LitJson;
namespace Fraunhofer.Fit.IoT.LoraMap.Model {
public class WeatherWarnings {
private readonly Settings settings;
private Thread bgthread;
private readonly WebRequests webrequests = new WebRequests();
public List<Warning> Warnungen { get; private set; }
public WeatherWarnings(Settings settings) {
this.settings = settings;
this.StartBackgroundThread();
}
private void StartBackgroundThread() {
this.bgthread = new Thread(this.BackGroundRunner);
this.bgthread.Start();
}
private void BackGroundRunner() {
while(true) {
List<Warning> ret = new List<Warning>();
foreach(Int32 item in this.settings.GetWeatherCellIds()) {
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) {
foreach (JsonData warning in json["features"]) {
try {
ret.Add(new Warning(warning));
} catch { }
}
}
} catch { }
}
this.Warnungen = ret;
Thread.Sleep(60 * 1000);
}
}
internal void Dispose() => this.bgthread.Abort();
public class Warning {
public Warning(JsonData warning) {
this.Id = warning["id"].ToString();
this.From = warning["properties"]["SENT"].ToString();
this.To = warning["properties"]["EXPIRES"].ToString();
this.Location = warning["properties"]["NAME"].ToString();
this.Type = warning["properties"]["EVENT"].ToString().ToLower();
this.Level = warning["properties"]["SEVERITY"].ToString().ToLower();
this.Headline = warning["properties"]["HEADLINE"].ToString();
this.Body = warning["properties"]["DESCRIPTION"].ToString();
this.Instructions = warning["properties"]["INSTRUCTION"] != null ? warning["properties"]["INSTRUCTION"].ToString() : "";
}
public String Id { get; }
public String From { get; }
public String To { get; }
public String Location { get; }
public String Type { get; }
public String Level { get; }
public String Headline { get; }
public String Body { get; }
public String Instructions { get; }
}
}
}
/* https://maps.dwd.de/geoserver/wfs?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&typeName=dwd:Warnungen_Gemeinden&outputFormat=application/json&cql_filter=WARNCELLID=805314000
* {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": "Warnungen_Gemeinden.805314000.2.49.0.1.276.0.DWD.PVW.1565627520000.4edfa973-5fef-4b97-8990-7489828dbe5b.DEU",
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[ 7.2072, 50.7395 ],
[ 7.1534, 50.7599 ],
[ 7.1255, 50.7744 ],
[ 7.105, 50.7622 ],
[ 7.0768, 50.7679 ],
[ 7.0666, 50.7705 ],
[ 7.0378, 50.7558 ],
[ 7.0256, 50.7054 ],
[ 7.0385, 50.6886 ],
[ 7.0255, 50.665 ],
[ 7.0473, 50.6391 ],
[ 7.0639, 50.6309 ],
[ 7.1054, 50.6595 ],
[ 7.1278, 50.6472 ],
[ 7.1564, 50.6547 ],
[ 7.1954, 50.6434 ],
[ 7.2119, 50.649 ],
[ 7.1972, 50.6648 ],
[ 7.1679, 50.7035 ],
[ 7.1969, 50.7138 ],
[ 7.2072, 50.7395 ]
]
]
]
},
"geometry_name": "THE_GEOM",
"properties": {
"AREADESC": "Bonn",
"NAME": "Stadt Bonn",
"WARNCELLID": 805314000,
"IDENTIFIER": "2.49.0.1.276.0.DWD.PVW.1565627520000.4edfa973-5fef-4b97-8990-7489828dbe5b.DEU",
"SENDER": "CAP@dwd.de",
"SENT": "2019-08-12T16:32:00Z",
"STATUS": "Actual",
"MSGTYPE": "Update",
"SOURCE": "PVW",
"SCOPE": "Public",
"CODE": "id:2.49.0.1.276.0.DWD.PVW.1565627520000.4edfa973-5fef-4b97-8990-7489828dbe5b",
"LANGUAGE": "de-DE",
"CATEGORY": "Met",
"EVENT": "GEWITTER",
"RESPONSETYPE": "Prepare",
"URGENCY": "Immediate",
"SEVERITY": "Minor",
"CERTAINTY": "Likely",
"EC_PROFILE": "2.1",
"EC_LICENSE": "Geobasisdaten: Copyright Bundesamt für Kartographie und Geodäsie, Frankfurt am Main, 2017",
"EC_II": "31",
"EC_GROUP": "THUNDERSTORM;WIND",
"EC_AREA_COLOR": "255 255 0",
"EFFECTIVE": "2019-08-12T16:32:00Z",
"ONSET": "2019-08-12T16:32:00Z",
"EXPIRES": "2019-08-12T17:00:00Z",
"SENDERNAME": "DWD / Nationales Warnzentrum Offenbach",
"HEADLINE": "Amtliche WARNUNG vor GEWITTER",
"DESCRIPTION": "Von Südwesten ziehen einzelne Gewitter auf. Dabei gibt es Windböen mit Geschwindigkeiten um 60 km/h (17m/s, 33kn, Bft 7).",
"INSTRUCTION": "ACHTUNG! Hinweis auf mögliche Gefahren: Örtlich kann es Blitzschlag geben. Bei Blitzschlag besteht Lebensgefahr!",
"WEB": "http://www.wettergefahren.de",
"CONTACT": "Deutscher Wetterdienst",
"PARAMETERNAME": "Böen;Gewitter;Gewitteraufzugsrichtung",
"PARAMETERVALUE": "~60 [km/h];einzelne;SW",
"ALTITUDE": 0,
"CEILING": 9842.5197,
"bbox": [ 7.0255, 50.6309, 7.2119, 50.7744 ]
}
}
],
"totalFeatures": 1,
"numberMatched": 1,
"numberReturned": 1,
"timeStamp": "2019-08-12T16:42:20.743Z",
"crs": {
"type": "name",
"properties": { "name": "urn:ogc:def:crs:EPSG::4326" }
},
"bbox": [ 50.6309, 7.0255, 50.7744, 7.2119 ]
}
*/

View File

@ -9,22 +9,19 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
InIReader.SetSearchPath(new List<String>() { "/etc/loramap", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\loramap" });
if (!InIReader.ConfigExist("settings")) {
Helper.WriteError("settings.ini not found!");
Console.ReadLine();
_ = Console.ReadLine();
return;
}
if(!InIReader.ConfigExist("requests")) {
Helper.WriteError("requests.ini not found!");
Console.ReadLine();
_ = Console.ReadLine();
return;
}
InIReader ini = InIReader.GetInstance("settings");
Dictionary<String, String> backenddata = ini.GetSection("mqtt");
backenddata.Add("topic", "lora/#;camera/#");
backenddata.Add("topic", "lora/#;camera/#;sfn/#");
ADataBackend b = (ADataBackend)ABackend.GetInstance(backenddata, ABackend.BackendType.Data);
new Server(b, ini.GetSection("webserver"), InIReader.GetInstance("requests"));
while(true) {
System.Threading.Thread.Sleep(1000);
}
_ = new Server(b, ini.GetSection("webserver"), InIReader.GetInstance("requests"));
}
}
}

View File

@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Fraunhofer FIT")]
[assembly: AssemblyProduct("Lora-Map")]
[assembly: AssemblyCopyright("Copyright © 2018 - 10.07.2019")]
[assembly: AssemblyCopyright("Copyright © 2018 - 30.08.2019")]
[assembly: AssemblyTrademark("Fraunhofer FIT, BlubbFish")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("de-DE")]
@ -33,8 +33,8 @@ using System.Runtime.InteropServices;
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.8")]
[assembly: AssemblyFileVersion("1.2.8")]
[assembly: AssemblyVersion("1.2.9")]
[assembly: AssemblyFileVersion("1.2.9")]
/*
* 1.1.1 Add Debian package config
@ -53,4 +53,5 @@ using System.Runtime.InteropServices;
* 1.2.6 New Types of marker for person
* 1.2.7 Reorganise a lot of things, add Support for Cameradata
* 1.2.8 Improving the UI
* 1.2.9 The PüMa Release
*/

View File

@ -15,13 +15,19 @@ 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> cameras = new SortedDictionary<String, Camera>();
private readonly SortedDictionary<String, Crowd> crowds = new SortedDictionary<String, Crowd>();
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 JsonData marker;
private readonly Settings settings;
private readonly WeatherWarnings weather;
private readonly Dictionary<String, Marker> markertable = new Dictionary<String, Marker>();
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();
public Server(ADataBackend backend, Dictionary<String, String> settings, InIReader requests) : base(backend, settings, requests) {
this.logger.SetPath(settings["loggingpath"]);
@ -29,7 +35,12 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
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.StartListen();
this.WaitForShutdown();
this.Dispose();
}
private void AdminModelUpdateNames(Object sender, EventArgs e) {
@ -42,7 +53,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
private void CheckJsonFiles() {
if(!Directory.Exists("json")) {
Directory.CreateDirectory("json");
_ = Directory.CreateDirectory("json");
}
if(!File.Exists("json/names.json")) {
File.WriteAllText("json/names.json", "{}");
@ -50,6 +61,9 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
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) {
@ -84,19 +98,31 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
Console.WriteLine("PANIC erhalten!");
} else if(Camera.CheckJson(d) && ((String)mqtt.From).Contains("camera/count")) {
String cameraid = Camera.GetId(d);
if(this.cameras.ContainsKey(cameraid)) {
this.cameras[cameraid].Update(d);
} else {
this.cameras.Add(cameraid, new Camera(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") && Crowd.CheckJsonCrowdDensityLocal(d)) ||
(((String)mqtt.From).Contains("sfn/fighting_detection") && Crowd.CheckJsonFightingDetection(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);
if(this.crowds.ContainsKey(cameraid)) {
this.crowds[cameraid].Update(d);
} else {
this.crowds.Add(cameraid, new Crowd(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));
}
}
}
} catch(Exception e) {
@ -106,13 +132,28 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
protected override Boolean SendWebserverResponse(HttpListenerContext cont) {
try {
if(cont.Request.Url.PathAndQuery.StartsWith("/loc")) {
return SendJsonResponse(this.positions, cont);
} else if(cont.Request.Url.PathAndQuery.StartsWith("/panic")) {
return SendJsonResponse(this.alarms, cont);
} else if(cont.Request.Url.PathAndQuery.StartsWith("/icons/marker/Marker.svg") && cont.Request.Url.PathAndQuery.Contains("?")) {
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 }
}, 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(cont.Request) },
{ "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)) {
if (!this.markertable.ContainsKey(hash)) {
this.markertable.Add(hash, new Marker(hash));
}
cont.Response.ContentType = "image/svg+xml";
@ -121,25 +162,11 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
cont.Response.OutputStream.Write(buf, 0, buf.Length);
Console.WriteLine("200 - " + cont.Request.Url.PathAndQuery);
return true;
} else if(cont.Request.Url.PathAndQuery.StartsWith("/currenttime")) {
return SendJsonResponse(new Dictionary<String, DateTime>() { { "utc", DateTime.UtcNow } }, cont);
} else if(cont.Request.Url.PathAndQuery.StartsWith("/admin")) {
} else if (cont.Request.Url.PathAndQuery.StartsWith("/admin")) {
return this.admin.ParseReuqest(cont);
} else if(cont.Request.Url.PathAndQuery.StartsWith("/getlayer")) {
return SendJsonResponse(this.FindMapLayer(cont.Request), cont);
} else if(cont.Request.Url.PathAndQuery.StartsWith("/maps/")) {
} else if (cont.Request.Url.PathAndQuery.StartsWith("/maps/")) {
return SendFileResponse(cont, "resources", false);
} else if(cont.Request.Url.PathAndQuery.StartsWith("/getgeo")) {
Byte[] buf = Encoding.UTF8.GetBytes(File.ReadAllText("json/geo.json"));
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("/cameracount")) {
return SendJsonResponse(this.cameras, cont);
} else if (cont.Request.Url.PathAndQuery.StartsWith("/crowdcount")) {
return SendJsonResponse(this.crowds, cont);
}
}
} catch(Exception e) {
Helper.WriteError("SendWebserverResponse(): 500 - " + e.Message + "\n\n" + e.StackTrace);
cont.Response.StatusCode = 500;
@ -182,5 +209,10 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
}
return ret;
}
public override void Dispose() {
this.weather.Dispose();
base.Dispose();
}
}
}

View File

@ -30,54 +30,42 @@
margin-left: 210px;
border-left: 1px solid black;
}
#content #nameeditor .title {
margin-bottom: 20px;
font-weight: bold;
}
#content #nameeditor #nametable {
#content .settingstable {
margin-left: 15px;
border-collapse: collapse;
border-collapse: separate;
}
#content #nameeditor #nametable thead {
#content .settingstable thead {
background-color: #CCCCCC;
background-color: rgba(0,0,0,0.2);
}
#content #nameeditor #nametable thead th {
#content .settingstable thead th {
text-align: left;
}
#content #nameeditor #nametable thead .rowid {
width: 60px;
}
#content #nameeditor #nametable thead .rowicon {
width: 65px;
}
#content #nameeditor #nametable thead .rowedit {
width: 50px;
}
#content #nameeditor #nametable thead .rowname {
width: 250px;
}
#content #nameeditor #nametable tbody tr:nth-child(odd) {
#content .settingstable tbody tr:nth-child(odd) {
background-color: #f39d9d;
background-color: rgba(20,0,250,0.1);
}
#content #nameeditor #nametable tbody tr:nth-child(even) {
#content .settingstable tbody tr:nth-child(even) {
background-color: #9c9eee;
background-color: rgba(250,59,0,0.1);
}
#content #nameeditor #nametable tbody tr:hover {
#content .settingstable tbody tr:hover {
background-color: #e4e1e1;
background-color: rgba(0,0,0,0.1);
}
#content #nameeditor #nametable tfoot {
#content .settingstable tfoot {
background-color: #e4e1e1;
background-color: rgba(0,0,0,0.1);
}
#content #nameeditor .pointer {
#content .pointer {
cursor: pointer;
}
#content #nameeditor #nametable tbody .name {
width: 55px;
#content #nameeditor .title {
margin-bottom: 20px;
font-weight: bold;
}
#iconeditor {
@ -113,4 +101,22 @@
#content #eximport .names textarea {
height: 120px;
width: 90%;
}
#content #settingseditor .title {
margin-bottom: 20px;
font-weight: bold;
}
#content #settingseditor .startloc,
#content #settingseditor .wetterwarnings,
#content #settingseditor .savesettings,
#content #settingseditor .gridradius {
margin-left: 15px;
}
#content #settingseditor .fightdedection,
#content #settingseditor .crowddensity {
margin-left: 15px;
margin-top: 20px;
}

View File

@ -11,9 +11,10 @@
<div id="header">Adminpannel Lora-Map</div>
<div id="menu">
<ul>
<li><a onclick="menu_names(); return false;" href="#">Namen und Icons</a></li>
<li><a onclick="menu_overlay(); return false;" href="#">Karteneditor</a></li>
<li><a onclick="menu_eximport(); return false;" href="#">Ex- und Import</a></li>
<li><a onclick="return AdminMenu.Names();" href="#">Namen und Icons</a></li>
<!-- <li><a onclick="return AdminMenu.Overlay();" href="#">Karteneditor</a></li> -->
<li><a onclick="return AdminMenu.Settings();" href="#">Einstellungen</a></li>
<li><a onclick="return AdminMenu.ExImport();" href="#">Ex- und Import</a></li>
</ul>
</div>
<div id="content">Wilkommen im Adminbereich</div>

View File

@ -1,44 +1,65 @@
function menu_names() {
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();
}
function menu_overlay() {
}
function menu_eximport() {
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) {
ExImport.ParseJson(ajaxnames.responseText, ajaxgeo.responseText);
}
};
ajaxgeo.open("GET", "/admin/get_json_geo", true);
ajaxgeo.send();
}
};
ajaxnames.open("GET", "/admin/get_json_names", true);
ajaxnames.send();
}
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'>";
html += "<thead><tr><th class='rowid'>ID</th><th class='rowname'>Name</th><th class='rowicon'>Icon</th><th class='rowedit'></th></tr></thead>";
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)) {
@ -53,12 +74,14 @@ var NamesEditor = {
} 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><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 += "<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>";
},
@ -119,9 +142,10 @@ var NamesEditor = {
},
Add: function () {
var newrow = document.createElement("tr");
newrow.innerHTML = "<td><input class='name'/></td>";
newrow.innerHTML += "<td><input /></td>";
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);
},
@ -135,7 +159,7 @@ var NamesEditor = {
}
var id = rows[i].children[0].innerText;
var name = rows[i].children[1].innerText;
namejson[id] = { "name": name };
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);
}
@ -164,16 +188,18 @@ var NamesEditor = {
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 class='name' value='" + id + "'/></td>";
el.innerHTML += "<td><input value='" + name + "'/></td>";
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) {
@ -183,6 +209,10 @@ var NamesEditor = {
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;
}
@ -193,6 +223,7 @@ var NamesEditor = {
} 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) {
@ -220,13 +251,17 @@ var NamesEditor = {
"</div>";
document.getElementsByTagName("body")[0].appendChild(ie);
},
CreateSelectBox: function (title, key, query, options, muliple, group) {
var html = title + ": ";
var eventtext = "NamesEditor.ChangeLinkPreview(\"" + key + "\",this.selectedOptions);";
if (typeof group !== "undefined") {
eventtext += " document.getElementById(\"" + group + "\"+this.value).style.display = \"block\";'";
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='" + eventtext + "'" + (typeof muliple !== "undefined" && muliple !== null ? " multiple" : "") + ">";
html += "<select" + onchange + (typeof muliple !== "undefined" && muliple !== null ? " multiple" : "") + ">";
if (typeof muliple === "undefined" || muliple === null) {
html += "<option>---</option>";
}
@ -320,15 +355,243 @@ var NamesEditor = {
}
};
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 = [];
}
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='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 };
}
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
};
}
ret.CrwodDensity = crowdjson;
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));
},
_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='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><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><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='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><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><img src='../icons/general/add.png' onclick='Settings.AddDensity()' class='pointer'></td></tr></tfoot>";
ret += "</table>";
return ret;
},
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><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><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);
},
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 (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><img src='../icons/general/edit.png' onclick='Settings.EditFight(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.DeleteFight(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><img src='../icons/general/edit.png' onclick='Settings.EditDensity(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.DeleteFight(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);
}
},
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><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><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) {
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();
@ -357,5 +620,19 @@ var ExImport = {
};
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);
}
};

View File

@ -59,12 +59,24 @@ object {
#menucollumn .pos {
background-image: url("icons/placeholder.png");
}
#menucollumn .filter {
background-image: url("icons/filter.png");
}
#menucollumn .admin {
background-image: url("icons/admin-with-cogwheels.png");
}
#menucollumn .info {
background-image: url("icons/information.png");
}
#menucollumn .weather {
background-image: url("icons/storm-in.png");
}
#menucollumn .weather.ac {
background-image: url("icons/storm-ac.png");
}
#menucollumn .suche {
background-image: url("icons/search.png");
}
#pannels {
position: absolute;
@ -89,6 +101,10 @@ object {
#pannels #pannels_pos .item {
margin: 4px;
}
#pannels #pannels_pos .item.filter {
opacity: 0.4;
background-color: rgba(1,1,1,0.2);
}
#pannels #pannels_pos .item .color {
float: left;
width: 2px;
@ -101,10 +117,10 @@ object {
margin-right: 5px;
}
#pannels #pannels_pos .item .icon img {
height: 40px;
width: 40px;
margin-left: 3px;
}
height: 40px;
width: 40px;
margin-left: 3px;
}
#pannels #pannels_pos .item .line1 .name {
font-weight: bold;
}
@ -203,6 +219,103 @@ object {
margin-left: 70px;
}
#pannels #pannels_weather {
margin: 5px;
display: none;
}
#pannels #pannels_weather h1 {
margin: 0;
font-size: 20px;
text-align: center;
}
#pannels #pannels_weather .alertitem {
padding: 5px;
margin-bottom: 10px;
}
#pannels #pannels_weather .alertitem.minor {
background-color: #ffeb3b;
}
#pannels #pannels_weather .alertitem.moderate {
background-color: #fb8c00;
}
#pannels #pannels_weather .alertitem.severe {
background-color: #e53935;
}
#pannels #pannels_weather .alertitem.extreme {
background-color: #880e4f;
}
#pannels #pannels_weather .alertitem.hitze {
background-color: #c9f;
}
#pannels #pannels_weather .alertitem .head {
font-weight: bold;
display: block;
font-size: 14px;
}
#pannels #pannels_weather .alertitem .ort {
display: block;
text-align: right;
margin-bottom: 10px;
}
#pannels #pannels_weather .alertitem .text {
display: block;
margin-bottom: 10px;
}
#pannels #pannels_filter {
margin: 5px;
display: none;
}
#pannels #pannels_filter h1 {
font-size: 16px;
}
#pannels #pannels_filter select {
height: 140px;
width: 235px;
}
#pannels #pannels_suche {
display: none;
padding: 5px;
}
#pannels #pannels_suche .searchtitle {
font-weight: bold;
font-size: 13px;
}
#pannels #pannels_suche input {
width: 220px;
margin-top: 5px;
}
#pannels #pannels_suche #search_results {
border-top: 1px solid black;
margin-top: 10px;
padding-top: 10px;
}
#pannels #pannels_suche #search_results .result {
background-color: rgba(0,0,0,0.2);
margin-bottom: 5px;
cursor: pointer;
}
#pannels #pannels_suche #search_results .result .text {
display: inline-block;
width: 200px;
}
#pannels #pannels_suche #search_results .result .text .title {
font-weight: bold;
display: block;
}
#pannels #pannels_suche #search_results .result .text .desc {
display: block;
}
#pannels #pannels_suche #search_results .result .box {
display: inline-block;
height: 25px;
width: 15px;
border-style: solid;
border-width: 2px;
vertical-align: top;
}
#overlays #cameracount {
position: absolute;
top: 10px;

Binary file not shown.

After

Width:  |  Height:  |  Size: 848 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -10,15 +10,36 @@
<body>
<div id="bigmap"></div>
<div id="menucollumn">
<span class="pos" onclick="showHidePanel('pannels_pos');"></span>
<span class="admin" onclick="showHidePanel('pannels_admin');"></span>
<span class="info" onclick="showHidePanel('pannels_version');"></span>
<span class="pos" onclick="MenuObject.ShowHidePanel('pannels_pos');"></span>
<span class="filter" onclick="MenuObject.ShowHidePanel('pannels_filter');"></span>
<span class="suche" onclick="MenuObject.ShowHidePanel('pannels_suche');"></span>
<span class="weather" onclick="MenuObject.ShowHidePanel('pannels_weather');" id="menucol_weather_icon"></span>
<span class="admin" onclick="MenuObject.ShowHidePanel('pannels_admin');"></span>
<span class="info" onclick="MenuObject.ShowHidePanel('pannels_version');"></span>
</div>
<div id="pannels">
<div id="pannels_pos"></div>
<div id="pannels_info">
<!-- Shows infos about selected device here, this will be cleand by js -->
</div>
<div id="pannels_filter">
<h1>Angezeigte Gruppen</h1>
<select multiple onchange="MarkerObject.ChangeFilter(this);">
<option value="fw">Feuerwehr</option>
<option value="sani">Sanitäter</option>
<option value="pol">Polizei</option>
<option value="oa">Ordnungsamt</option>
<option value="si">Sicherheitsdienst</option>
<option value="thw">Technisches Hilfswerk</option>
<option value="crew">Veranstalter</option>
<option value="dev">Entwickler</option>
</select><br />
<span>(Klicken Sie mit <strong>STRG</strong> in das Formular um mehrere Gruppen auszuwählen)</span><br /><br />
<span>Sind keine Gruppen ausgewählt, werden alle Icons angezeigt, egal welcher Gruppe sie angehören.</span>
</div>
<div id="pannels_weather">
<h1>Keine Gefahren</h1>
</div>
<div id="pannels_admin">
Teste Login...
</div>
@ -34,9 +55,16 @@
<li><a href="https://www.freepik.com/" title="Freepik">Freepik</a> licensed <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></li>
<li><a href="http://www.famfamfam.com/about/" title="Silk Iconset">Silk Iconset</a> licensed <a href="http://creativecommons.org/licenses/by/2.5/" title="Creative Commons BY 2.5" target="_blank">CC 2.5 BY</a></li>
<li><a href="https://www.flaticon.com/authors/those-icons" title="Those Icons">Those Icons</a> licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></li>
<li><a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> licensed by <a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a></li>
<li><a href="https://www.flaticon.com/authors/dimitry-miroliubov" title="Dimitry Miroliubov">Dimitry Miroliubov</a> from <a href="https://www.flaticon.com/" title="Flaticon">flaticon.com</a></li>
</ul>
</div>
</div>
<div id="pannels_suche">
<span class="searchtitle">Standnummer:</span><br />
<input onkeyup="MenuObject.SearchInGeoJson(this.value);"/>
<div id="search_results"></div>
</div>
</div>
<div id="overlays">
<div id="cameracount"></div>

View File

@ -1,43 +1,87 @@
setInterval(timecorrectionrunner, 60000);
timecorrectionrunner();
function timecorrectionrunner() {
var timecorrection = new XMLHttpRequest();
timecorrection.onreadystatechange = parseAjaxTimecorrection;
timecorrection.open("GET", "/currenttime", true);
timecorrection.send();
}
var timeOffset = 0;
function parseAjaxTimecorrection() {
if (this.readyState === 4 && this.status === 200) {
utcobject = JSON.parse(this.responseText);
var FunctionsObject = {
_internalTimeOffset: 0,
Start: function () {
setInterval(this._Runner60000, 60000);
setInterval(this._Runner1000, 1000);
this._Runner60000();
this._Runner1000();
this._RunnerOnce();
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"]);
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"]);
}
};
getonce.open("GET", "/getonce", true);
getonce.send();
},
_ParseAJAX: function (utcobject) {
if (utcobject.hasOwnProperty("utc")) {
timeOffset = Date.now() - Date.parse(utcobject["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);
if (type === "diffraw") {
return diff;
}
if (type === "difftextn" && diff < 0) {
diff = diff * -1;
}
var isneg = false;
if (diff < 0) {
isneg = true;
diff = diff * -1;
}
if (diff < 60) {
return (isneg ? "-" : "") + diff + " s";
}
if (diff < 60 * 60) {
return (isneg ? "-" : "") + Math.floor(diff / 60) + " m";
}
if (diff < 60 * 60 * 24) {
return (isneg ? "-" : "") + Math.floor(diff / (60 * 60)) + " h";
}
return (isneg ? "-" : "") + Math.floor(diff / (60 * 60 * 24)) + " d";
} else if (type === "str") {
var date = new Date(Date.parse(timestr) + this._internalTimeOffset);
var str = date.toLocaleString();
return str;
}
}
}
function timeCalculation(timestr, type) {
if (type === "diffraw" || type === "difftext") {
var diff = Math.round((Date.now() - Date.parse(timestr) - timeOffset) / 1000);
if (type === "diffraw") {
return diff;
}
if (diff < 60) {
return diff + " s";
}
if (diff < 60 * 60) {
return Math.floor(diff / 60) + " m";
}
if (diff < 60 * 60 * 24) {
return Math.floor(diff / (60 * 60)) + " h";
}
return Math.floor(diff / (60 * 60 * 24)) + " d";
} else if (type === "str") {
var date = new Date(Date.parse(timestr) + timeOffset);
var str = date.toLocaleString();
return str;
}
}
}.Start();

View File

@ -1,197 +1,263 @@
var mymap = L.map('bigmap').setView(["{%START_LOCATION%}"], 16);
GetMapLayers();
function GetMapLayers() {
var layergetter = new XMLHttpRequest();
layergetter.onreadystatechange = function () {
if (layergetter.readyState === 4 && layergetter.status === 200) {
var maps = JSON.parse(layergetter.responseText);
var i = 0;
for (var key in maps) {
i++;
var MapObject = {
Map: {},
GeoJson: {},
_FightDedection: {},
_DensityAreas: {},
_SpecialMarkers: new Array(),
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);
},
_ParseAJAXLayers: function (maps) {
var i = 0;
for (var key in maps) {
i++;
}
if (i === 1) {
L.tileLayer(maps["online"]["url"], {
attribution: maps["online"]["attribution"],
minZoom: maps["online"]["minZoom"],
maxZoom: maps["online"]["maxZoom"]
}).addTo(this.Map);
} else {
var baseMaps = {};
for (key in maps) {
if (key !== "online") {
var basemap = L.tileLayer(maps[key]["url"], {
attribution: maps[key]["attribution"],
minZoom: maps[key]["minZoom"],
maxZoom: maps[key]["maxZoom"],
errorTileUrl: "css/icons/failtile.png"
});
basemap.addTo(this.Map);
baseMaps[maps[key]["title"]] = basemap;
break;
}
}
if (i === 1) {
L.tileLayer(maps["online"]["url"], {
attribution: maps["online"]["attribution"],
minZoom: maps["online"]["minZoom"],
maxZoom: maps["online"]["maxZoom"]
}).addTo(mymap);
} else {
var baseMaps = {};
for (key in maps) {
if (key !== "online") {
var basemap = L.tileLayer(maps[key]["url"], {
attribution: maps[key]["attribution"],
minZoom: maps[key]["minZoom"],
maxZoom: maps[key]["maxZoom"],
errorTileUrl: "css/icons/failtile.png"
});
basemap.addTo(mymap);
baseMaps[maps[key]["title"]] = basemap;
break;
}
for (key in maps) {
if (!baseMaps.hasOwnProperty(maps[key]["title"])) {
baseMaps[maps[key]["title"]] = L.tileLayer(maps[key]["url"], {
attribution: maps[key]["attribution"],
minZoom: maps[key]["minZoom"],
maxZoom: maps[key]["maxZoom"],
errorTileUrl: "css/icons/failtile.png"
});
}
for (key in maps) {
if (!baseMaps.hasOwnProperty(maps[key]["title"])) {
baseMaps[maps[key]["title"]] = L.tileLayer(maps[key]["url"], {
attribution: maps[key]["attribution"],
minZoom: maps[key]["minZoom"],
maxZoom: maps[key]["maxZoom"],
errorTileUrl: "css/icons/failtile.png"
});
}
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 }).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 }).addTo(this.Map);
}
},
_GenerateFightBoxes: function (fightdedection) {
for (var cameraid in fightdedection) {
this._FightDedection[cameraid] = L.polygon(fightdedection[cameraid], { color: 'black', weight: 1 }).addTo(this.Map);
this._FightDedection[cameraid].bindPopup("Fightdedection für Kamera: " + cameraid);
}
},
_ParseAJAXFightDedection: function (json) {
for (var cameraid in json) {
if (this._FightDedection.hasOwnProperty(cameraid)) {
var fight = json[cameraid];
var box = this._FightDedection[cameraid];
var diff = FunctionsObject.TimeCalculation(fight["LastUpdate"], "diffraw");
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' });
}
L.control.layers(baseMaps).addTo(mymap);
}
}
};
layergetter.open("GET", "/getlayer", true);
layergetter.send();
}
var SpecialMarkers = new Array();
GetGeoLayer();
function GetGeoLayer() {
var geogetter = new XMLHttpRequest();
geogetter.onreadystatechange = function () {
if (geogetter.readyState === 4 && geogetter.status === 200) {
var geo = JSON.parse(geogetter.responseText);
if (!(Object.keys(geo).length === 0 && geo.constructor === Object)) {
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);
}
},
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]
})
});
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"]
})
});
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(mymap);
},
_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();
}
}
};
geogetter.open("GET", "/getgeo", true);
geogetter.send();
}
mymap.on('zoomend', function () {
var currentZoom = mymap.getZoom();
if (currentZoom < 14) {
SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "0px";
elem._icon.style.marginLeft = "0px";
elem._icon.style.marginTop = "0px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "0px";
}
});
} else if (currentZoom === 14) {
SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "0px";
elem._icon.style.marginLeft = "0px";
elem._icon.style.marginTop = "0px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "6px";
}
});
} else if (currentZoom === 15) {
SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "0px";
elem._icon.style.marginLeft = "0px";
elem._icon.style.marginTop = "0px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "9px";
}
});
} else if (currentZoom === 16) {
SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "5px";
elem._icon.style.marginLeft = "-4px";
elem._icon.style.marginTop = "-4px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "13px";
}
});
} else if (currentZoom === 17) {
SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "5px";
elem._icon.style.marginLeft = "-4px";
elem._icon.style.marginTop = "-4px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "16px";
}
});
} else if (currentZoom === 18) {
SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "8px";
elem._icon.style.marginLeft = "-5px";
elem._icon.style.marginTop = "-6px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "25px";
}
});
} else if (currentZoom === 19) {
SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "14px";
elem._icon.style.marginLeft = "-8px";
elem._icon.style.marginTop = "-11px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "45px";
},
_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);
}
},
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]
})
});
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"]
})
});
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);
}
},
_SetupMapZoomFontsize: function () {
this.Map.on('zoomend', function () {
var currentZoom = MapObject.Map.getZoom();
if (currentZoom < 14) {
MapObject._SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "0px";
elem._icon.style.marginLeft = "0px";
elem._icon.style.marginTop = "0px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "0px";
}
});
} else if (currentZoom === 14) {
MapObject._SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "0px";
elem._icon.style.marginLeft = "0px";
elem._icon.style.marginTop = "0px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "6px";
}
});
} else if (currentZoom === 15) {
MapObject._SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "0px";
elem._icon.style.marginLeft = "0px";
elem._icon.style.marginTop = "0px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "9px";
}
});
} else if (currentZoom === 16) {
MapObject._SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "5px";
elem._icon.style.marginLeft = "-4px";
elem._icon.style.marginTop = "-4px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "13px";
}
});
} else if (currentZoom === 17) {
MapObject._SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "5px";
elem._icon.style.marginLeft = "-4px";
elem._icon.style.marginTop = "-4px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "16px";
}
});
} else if (currentZoom === 18) {
MapObject._SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "8px";
elem._icon.style.marginLeft = "-5px";
elem._icon.style.marginTop = "-6px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "25px";
}
});
} else if (currentZoom === 19) {
MapObject._SpecialMarkers.forEach(function (elem, index) {
if (elem.feature.properties["description"] === "snumber") {
elem._icon.style.fontSize = "14px";
elem._icon.style.marginLeft = "-8px";
elem._icon.style.marginTop = "-11px";
}
if (elem.feature.properties["description"] === "coord") {
elem._icon.style.fontSize = "45px";
}
});
}
});
},
_SetupClickHandler: function () {
this.Map.on("click", this._HidePanel);
},
_HidePanel: function (e) {
MenuObject.ShowHidePanel(null);
},
JumpTo: function (lat, lon) {
this.Map.flyTo([lat, lon], 19);
}
});
mymap.on("click", hidePanel);
function hidePanel(e) {
showHidePanel(null);
}
}.Start();

View File

@ -1,27 +1,18 @@
setInterval(datarunner, 1000);
function datarunner() {
var loc = new XMLHttpRequest();
loc.onreadystatechange = parseAjaxLoc;
loc.open("GET", "/loc", true);
loc.send();
var panic = new XMLHttpRequest();
panic.onreadystatechange = parseAjaxPanic;
panic.open("GET", "/panic", true);
panic.send();
}
var markers = {};
var serverLocation = {};
//https://leafletjs.com/reference-1.4.0.html#marker
function parseAjaxLoc() {
if (this.readyState === 4 && this.status === 200) {
serverLocation = JSON.parse(this.responseText);
for (var key in serverLocation) {
if (serverLocation.hasOwnProperty(key)) {
var positionItem = serverLocation[key];
var MarkerObject = {
_Markers: {},
PanicData: {},
LocationData: {},
VisibleMarkers: {},
Start: function () {
return this;
},
_ParseAJAXLoc: function (serverLocation) {
this.LocationData = serverLocation;
for (var key in this.LocationData) {
if (this.LocationData.hasOwnProperty(key)) {
var positionItem = this.LocationData[key];
if (positionItem['Latitude'] !== 0 || positionItem['Longitude'] !== 0) {
if (!markers.hasOwnProperty(key)) {
if (!this._Markers.hasOwnProperty(key)) {
var marker = null;
if (positionItem['Icon'] === null) {
marker = L.marker([positionItem['Latitude'], positionItem['Longitude']], { 'title': positionItem['Name'] });
@ -34,67 +25,80 @@ function parseAjaxLoc() {
});
marker = L.marker([positionItem['Latitude'], positionItem['Longitude']], { 'title': positionItem['Name'], 'icon': myIcon });
}
markers[key] = marker.addTo(mymap).on("click", showMarkerInfo, key);
this._Markers[key] = marker.addTo(MapObject.Map).on("click", function () { MenuObject.statusToDevice = this; MenuObject.ShowHidePanel("pannels_info"); }, key);
} else {
markers[key].setLatLng([positionItem['Latitude'], positionItem['Longitude']]);
this._Markers[key].setLatLng([positionItem['Latitude'], positionItem['Longitude']]);
if (positionItem['Icon'] !== null) {
if (markers[key]._icon.children.length === 0) {
markers[key].setIcon(L.divIcon({
if (this._Markers[key]._icon.children.length === 0) {
this._Markers[key].setIcon(L.divIcon({
className: 'pos-marker',
iconSize: [56, 80],
iconAnchor: [0, 80],
html: '<img src="' + positionItem['Icon'] + '" height="80" width="56" />'
}));
} else if (markers[key]._icon.children[0].hasAttribute("src")) {
var old = markers[key]._icon.children[0]["src"].substring(markers[key]._icon.children[0]["src"].indexOf("/", 7) + 1);
} else if (this._Markers[key]._icon.children[0].hasAttribute("src")) {
var old = this._Markers[key]._icon.children[0]["src"].substring(this._Markers[key]._icon.children[0]["src"].indexOf("/", 7) + 1);
if (old !== positionItem['Icon']) {
markers[key]._icon.children[0]["src"] = positionItem['Icon'];
this._Markers[key]._icon.children[0]["src"] = positionItem['Icon'];
}
}
} else {
if (markers[key]._icon.children.length === 1 && markers[key]._icon.children[0].hasAttribute("src")) {
markers[key].removeFrom(mymap);
markers[key] = L.marker([positionItem['Latitude'], positionItem['Longitude']], { 'title': positionItem['Name'] }).addTo(mymap).on("click", showMarkerInfo, key);
if (this._Markers[key]._icon.children.length === 1 && this._Markers[key]._icon.children[0].hasAttribute("src")) {
this._Markers[key].removeFrom(MapObject.Map);
this._Markers[key] = L.marker([positionItem['Latitude'], positionItem['Longitude']], { 'title': positionItem['Name'] }).addTo(MapObject.Map).on("click", function () { MenuObject.statusToDevice = this; MenuObject.ShowHidePanel("pannels_info"); }, key);
}
}
}
var lasttime = timeCalculation(positionItem['Recievedtime'], "diffraw");
if (lasttime <= 5 * 60) {
markers[key]._icon.style.opacity = 1;
} else if (lasttime > 5 * 60 && lasttime <= 15 * 60) {
markers[key]._icon.style.opacity = 0.9 - (lasttime - 5 * 60) / (15 * 60 - 5 * 60) * (0.9 - 0.7);
} else if (lasttime > 15 * 60 && lasttime <= 30 * 60) {
markers[key]._icon.style.opacity = 0.7 - (lasttime - 15 * 60) / (30 * 60 - 15 * 60) * (0.7 - 0.5);
} else if (lasttime > 30 * 60 && lasttime <= 60 * 60) {
markers[key]._icon.style.opacity = 0.5 - (lasttime - 30 * 60) / (30 * 60 - 30 * 60) * (0.5 - 0.25);
} else if (lasttime > 60 * 60) {
markers[key]._icon.style.opacity = 0.25;
if (positionItem.Group !== null && this.VisibleMarkers.hasOwnProperty("___isset") && !this.VisibleMarkers.hasOwnProperty(positionItem.Group)) {
this._Markers[key]._icon.style.opacity = 0;
} else {
var lasttime = FunctionsObject.TimeCalculation(positionItem['Recievedtime'], "diffraw");
if (lasttime <= 5 * 60) {
this._Markers[key]._icon.style.opacity = 1;
} else if (lasttime > 5 * 60 && lasttime <= 15 * 60) {
this._Markers[key]._icon.style.opacity = 0.9 - (lasttime - 5 * 60) / (15 * 60 - 5 * 60) * (0.9 - 0.7);
} else if (lasttime > 15 * 60 && lasttime <= 30 * 60) {
this._Markers[key]._icon.style.opacity = 0.7 - (lasttime - 15 * 60) / (30 * 60 - 15 * 60) * (0.7 - 0.5);
} else if (lasttime > 30 * 60 && lasttime <= 60 * 60) {
this._Markers[key]._icon.style.opacity = 0.5 - (lasttime - 30 * 60) / (30 * 60 - 30 * 60) * (0.5 - 0.25);
} else if (lasttime > 60 * 60) {
this._Markers[key]._icon.style.opacity = 0.25;
}
}
}
}
}
updateStatus();
update_pannels_info();
}
}
var serverPanic = {};
function parseAjaxPanic() {
if (this.readyState === 4 && this.status === 200) {
serverPanic = JSON.parse(this.responseText);
for (var id in serverPanic) {
if (serverPanic.hasOwnProperty(id)) {
var alertItem = serverPanic[id];
if (markers.hasOwnProperty(id)) {
var marker = markers[id];
if (timeCalculation(alertItem["Recievedtime"], "diffraw") <= 10 && marker._icon.className.indexOf(" marker-alert") === -1) {
marker._icon.className += " marker-alert";
showMarkerInfoPerId(id);
} else if (timeCalculation(alertItem["Recievedtime"], "diffraw") > 10 && marker._icon.className.indexOf(" marker-alert") !== -1) {
marker._icon.className = marker._icon.className.replace(" marker-alert", "");
MenuObject.UpdateStatus();
MenuObject._Update_pannels_info();
},
_ParseAJAXPanic: function (serverPanic) {
this.PanicData = serverPanic;
for (var id in this.PanicData) {
if (this.PanicData.hasOwnProperty(id)) {
var alertItem = this.PanicData[id];
if (this._Markers.hasOwnProperty(id)) {
var marker = this._Markers[id];
if (!(this.LocationData[id].Group !== null && this.VisibleMarkers.hasOwnProperty("___isset") && !this.VisibleMarkers.hasOwnProperty(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);
} else if (FunctionsObject.TimeCalculation(alertItem["Recievedtime"], "diffraw") > 10 && marker._icon.className.indexOf(" marker-alert") !== -1) {
marker._icon.className = marker._icon.className.replace(" marker-alert", "");
}
}
}
}
}
},
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();

View File

@ -1,175 +1,219 @@
var visiblePanel = null;
function showHidePanel(name) {
if (visiblePanel === null && name !== null) {
document.getElementById("pannels").style.display = "block";
document.getElementById(name).style.display = "block";
visiblePanel = name;
if (typeof window["update_" + name] === "function") {
window["update_" + name]();
}
} else if (visiblePanel === name && name !== "pannels_info" || name === null) {
document.getElementById("pannels").style.display = "none";
if (visiblePanel !== null) {
document.getElementById(visiblePanel).style.display = "none";
}
visiblePanel = null;
} else {
document.getElementById(visiblePanel).style.display = "none";
document.getElementById(name).style.display = "block";
visiblePanel = name;
if (typeof window["update_" + name] === "function") {
window["update_" + name]();
}
}
}
var statusToDevice = null;
function showMarkerInfo(e) {
statusToDevice = this;
showHidePanel("pannels_info");
}
function showMarkerInfoPerId(id) {
statusToDevice = id;
showHidePanel("pannels_info");
}
function showMarkerInfoMenu() {
statusToDevice = this.getAttribute("rel");
showHidePanel("pannels_info");
}
function update_pannels_info() {
document.getElementById("pannels_info").innerHTML = "";
if (serverLocation.hasOwnProperty(statusToDevice)) {
var positionItem = serverLocation[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>";
if (positionItem["Fix"]) {
html += "<div class=\"gps\" style=\"color: green;\">GPS-Empfang</div>";
var MenuObject = {
statusToDevice: null,
_visiblePanel: null,
_overviewStatus: new Array(),
Start: function () {
return this;
},
ShowHidePanel: function (name) {
if (this._visiblePanel === null && name !== null) {
document.getElementById("pannels").style.display = "block";
document.getElementById(name).style.display = "block";
this._visiblePanel = name;
if (typeof MenuObject["_Update_" + name] === "function") {
MenuObject["_Update_" + name]();
}
} else if (this._visiblePanel === name && name !== "pannels_info" || name === null) {
document.getElementById("pannels").style.display = "none";
if (this._visiblePanel !== null) {
document.getElementById(this._visiblePanel).style.display = "none";
}
this._visiblePanel = null;
} else {
html += "<div class=\"gps\" style=\"color: red;\">kein GPS-Empfang</div>";
document.getElementById(this._visiblePanel).style.display = "none";
document.getElementById(name).style.display = "block";
this._visiblePanel = name;
if (typeof MenuObject["_Update_" + name] === "function") {
MenuObject["_Update_" + name]();
}
}
html += "<div class=\"coord\">" + positionItem["UTM"]["Base"] + " <span style=\"color: #b1a831;\">" + positionItem["UTM"]["FieldWidth"] + "</span><span style=\"color: #218c00;\">" + positionItem["UTM"]["Width"] + "</span> <span style=\"color: #b1a831;\">" + positionItem["UTM"]["FieldHeight"] + "</span><span style=\"color: #218c00;\">" + positionItem["UTM"]["Height"] + "</span></div>";
html += "<div class=\"height\"><span class=\"bold\">Höhe:</span> " + positionItem["Height"].toFixed(1) + " m</div>";
html += "<div class=\"hdop\"><span class=\"bold\">HDOP:</span> " + positionItem["Hdop"].toFixed(1) + "</div>";
html += "<div class=\"lanlot\"><span class=\"bold\">Dezimal:</span> " + positionItem["Latitude"].toFixed(5) + ", " + positionItem["Longitude"].toFixed(5) + "</div>";
html += "<div class=\"lastgps\"><span class=\"bold\">Letzter Wert:</span> Vor: " + timeCalculation(positionItem["Lastgpspostime"], "difftext") + "</div>";
html += "<div class=\"update\"><span class=\"bold\">Update:</span> " + timeCalculation(positionItem["Recievedtime"], "str") + "<br><span class=\"bold\">Vor:</span> " + timeCalculation(positionItem["Recievedtime"], "difftext") + "</div>";
html += "<div><span class=\"bold\">RSSI:</span> " + positionItem["Rssi"] + ", <span class=\"bold\">SNR:</span> " + positionItem["Snr"] + "</div>";
if (serverPanic.hasOwnProperty(statusToDevice)) {
var panicData = serverPanic[statusToDevice];
if (panicData["ButtonPressed"].length > 0) {
html += "<div class='alerts'><span class=\"bold\">Alerts:</span>";
for (var i = 0; i < panicData["ButtonPressed"].length; i++) {
html += "<span class='panicitem'>" + timeCalculation(panicData["ButtonPressed"][i], "str")+" (vor " + timeCalculation(panicData["ButtonPressed"][i],"difftext")+")</span>";
},
ShowMarkerInfoPerId: function (id) {
this.statusToDevice = id;
this.ShowHidePanel("pannels_info");
},
UpdateStatus: function () {
for (var id in MarkerObject.LocationData) {
if (MarkerObject.LocationData.hasOwnProperty(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]);
}
html += "</div>";
if (positionItem.Group !== null && MarkerObject.VisibleMarkers.hasOwnProperty("___isset") && !MarkerObject.VisibleMarkers.hasOwnProperty(positionItem.Group)) {
if (this._overviewStatus[id].className.indexOf("filter") === -1) {
this._overviewStatus[id].className = "item filter";
}
} else {
if (this._overviewStatus[id].className.indexOf("filter") !== -1) {
this._overviewStatus[id].className = "item";
}
}
this._UpdateOverviewElement(positionItem, id);
}
}
document.getElementById("pannels_info").innerHTML = html;
}
}
var overviewStatus = new Array();
function updateStatus() {
for (var id in serverLocation) {
if (serverLocation.hasOwnProperty(id)) {
var positionItem = serverLocation[id];
if (typeof overviewStatus[id] === "undefined") {
overviewStatus[id] = createOverviewElement(positionItem, id);
document.getElementById("pannels_pos").appendChild(overviewStatus[id]);
}
updateOverviewElement(positionItem, id);
},
_UpdateOverviewElement: function (positionItem, id) {
if (positionItem["Batterysimple"] === 0) {
document.getElementById("overview-color-id-" + id).style.backgroundColor = "red";
} else if (positionItem["Batterysimple"] === 1 || positionItem["Batterysimple"] === 2) {
document.getElementById("overview-color-id-" + id).style.backgroundColor = "yellow";
} else if (positionItem["Batterysimple"] === 3 || positionItem["Batterysimple"] === 4) {
document.getElementById("overview-color-id-" + id).style.backgroundColor = "green";
}
}
}
function updateOverviewElement(positionItem, id) {
if (positionItem["Batterysimple"] === 0) {
document.getElementById("overview-color-id-" + id).style.backgroundColor = "red";
} else if (positionItem["Batterysimple"] === 1 || positionItem["Batterysimple"] === 2) {
document.getElementById("overview-color-id-" + id).style.backgroundColor = "yellow";
} else if (positionItem["Batterysimple"] === 3 || positionItem["Batterysimple"] === 4) {
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 (positionItem["Fix"]) {
document.getElementById("overview-gps-id-" + id).innerText = "GPS-Empfang";
document.getElementById("overview-gps-id-" + id).style.color = "green";
} else {
document.getElementById("overview-gps-id-" + id).innerText = "kein GPS-Empfang";
document.getElementById("overview-gps-id-" + id).style.color = "red";
}
document.getElementById("overview-update-id-" + id).innerText = "Letzte Werte: vor " + timeCalculation(positionItem["Recievedtime"], "difftext");
if (positionItem['Icon'] === null) {
var icon = document.getElementById("overview-icon-id-" + id);
if (icon.children[0].hasAttribute("rel")) {
document.getElementById("overview-icon-id-" + id).innerHTML = "<img src =\"icons/marker/map-marker.png\">";
document.getElementById("overview-name-id-" + id).innerText = positionItem["Name"];
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";
} else {
document.getElementById("overview-gps-id-" + id).innerText = "kein GPS-Empfang";
document.getElementById("overview-gps-id-" + id).style.color = "red";
}
} 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";
document.getElementById("overview-update-id-" + id).innerText = "Letzte Werte: vor " + FunctionsObject.TimeCalculation(positionItem["Recievedtime"], "difftext");
if (positionItem['Icon'] === null) {
var icon = document.getElementById("overview-icon-id-" + id);
if (icon.children[0].hasAttribute("rel")) {
document.getElementById("overview-icon-id-" + id).innerHTML = "<img src =\"icons/marker/map-marker.png\">";
}
} else {
document.getElementById("overview-icon-id-" + id).innerHTML = "<img src=\"" + positionItem['Icon'] + "&marker-bg=hidden" + "\" rel='svg'/>";
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";
}
} else {
document.getElementById("overview-icon-id-" + id).innerHTML = "<img src=\"" + positionItem['Icon'] + "&marker-bg=hidden" + "\" rel='svg'/>";
}
}
},
_CreateOverviewElement: function (positionItem, id) {
var divItem = document.createElement("div");
divItem.className = "item";
divItem.onclick = function showMarkerInfoMenu() {
MenuObject.statusToDevice = this.getAttribute("rel");
MenuObject.ShowHidePanel("pannels_info");
};
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>";
} else {
divItem.innerHTML += "<span class=\"icon\" id=\"overview-icon-id-" + id + "\"><img src=\"icons/marker/map-marker.png\" /></span>";
}
divItem.innerHTML += "<div class=\"line1\">" +
"<span class=\"name\" id=\"overview-name-id-" + id + "\"></span>" +
"<span class=\"akku\"><img id=\"overview-akkuimg-id-" + id + "\" src=\"icons/akku/" + positionItem["Batterysimple"] + "-4.png\"></span>" +
"</div>";
divItem.innerHTML += "<div class=\"line2\" style=\"color: red;\" id=\"overview-gps-id-" + id + "\">kein GPS-Empfang</div>";
divItem.innerHTML += "<div class=\"line3\" id=\"overview-update-id-" + id + "\">Letzte Werte: vor " + FunctionsObject.TimeCalculation(positionItem["Recievedtime"], "difftext") + "</div>";
return divItem;
},
_ParseAJAXPannelAdmin: function (loggedin) {
if (!loggedin) {
var html = "<h3>Login to Adminpannel</h3><form onsubmit='MenuObject.SubmitLoginForm(); return false;'>";
html += "<div><span class='label'>Username:</span><input id='pannels_admin_name'></div>";
html += "<div><span class='label'>Passwort:</span><input type='password' id='pannels_admin_pass'></div>";
html += "<div><span class='login'><input type='submit'></span></div></form>";
document.getElementById("pannels_admin").innerHTML = html;
} else {
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)) {
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>";
if (positionItem["Fix"]) {
html += "<div class=\"gps\" style=\"color: green;\">GPS-Empfang</div>";
} else {
html += "<div class=\"gps\" style=\"color: red;\">kein GPS-Empfang</div>";
}
html += "<div class=\"coord\">" + positionItem["UTM"]["Base"] + " <span style=\"color: #b1a831;\">" + positionItem["UTM"]["FieldWidth"] + "</span><span style=\"color: #218c00;\">" + positionItem["UTM"]["Width"] + "</span> <span style=\"color: #b1a831;\">" + positionItem["UTM"]["FieldHeight"] + "</span><span style=\"color: #218c00;\">" + positionItem["UTM"]["Height"] + "</span></div>";
html += "<div class=\"height\"><span class=\"bold\">Höhe:</span> " + positionItem["Height"].toFixed(1) + " m</div>";
html += "<div class=\"hdop\"><span class=\"bold\">HDOP:</span> " + positionItem["Hdop"].toFixed(1) + "</div>";
html += "<div class=\"lanlot\"><span class=\"bold\">Dezimal:</span> " + positionItem["Latitude"].toFixed(5) + ", " + positionItem["Longitude"].toFixed(5) + "</div>";
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)) {
var panicData = MarkerObject.PanicData[this.statusToDevice];
if (panicData["ButtonPressed"].length > 0) {
html += "<div class='alerts'><span class=\"bold\">Alerts:</span>";
for (var i = 0; i < panicData["ButtonPressed"].length; i++) {
html += "<span class='panicitem'>" + FunctionsObject.TimeCalculation(panicData["ButtonPressed"][i], "str") + " (vor " + FunctionsObject.TimeCalculation(panicData["ButtonPressed"][i], "difftext") + ")</span>";
}
html += "</div>";
}
}
document.getElementById("pannels_info").innerHTML = html;
}
},
_Update_pannels_admin: function () {
var testadmin = new XMLHttpRequest();
testadmin.onreadystatechange = function () {
if (testadmin.readyState === 4 && testadmin.status === 403) {
MenuObject._ParseAJAXPannelAdmin(false);
} else if (testadmin.readyState === 4 && testadmin.status === 200) {
MenuObject._ParseAJAXPannelAdmin(true);
}
};
testadmin.open("GET", "/admin", true);
testadmin.send();
},
_ParseAJAXWeatherAlerts: function (json) {
if (json.length > 0) {
var html = "";
for (var i = 0; i < json.length; i++) {
var walert = json[i];
html += "<div class='alertitem " + walert.Level +" "+ walert.Type + "'>" +
"<span class='head'>" + walert.Headline + "</span>" +
"<span class='ort'>" + walert.Location + "</span>" +
"<span class='text'>" + walert.Body + (walert.Instructions !== "" ? "<br><br>" + walert.Instructions : "") + "</span>" +
"<span class='time'><b>Von:</b> ";
if (FunctionsObject.TimeCalculation(walert.From, "diffraw") < 0) {
html += "in " + FunctionsObject.TimeCalculation(walert.From, "difftextn");
} else {
html += "vor " + FunctionsObject.TimeCalculation(walert.From, "difftext");
}
html += " <b>Bis:</b> in " + FunctionsObject.TimeCalculation(walert.To, "difftextn") + "</span>" +
"</div>";
}
document.getElementById("pannels_weather").innerHTML = html;
document.getElementById("menucol_weather_icon").className = "weather ac";
} else {
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.indexOf(searchtext) !== -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;
}
}
function createOverviewElement(positionItem, id) {
var divItem = document.createElement("div");
divItem.className = "item";
divItem.onclick = showMarkerInfoMenu;
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>";
} else {
divItem.innerHTML += "<span class=\"icon\" id=\"overview-icon-id-" + id + "\"><img src=\"icons/marker/map-marker.png\" /></span>";
}
divItem.innerHTML += "<div class=\"line1\">" +
"<span class=\"name\" id=\"overview-name-id-" + id + "\"></span>" +
"<span class=\"akku\"><img id=\"overview-akkuimg-id-" + id + "\" src=\"icons/akku/" + positionItem["Batterysimple"] + "-4.png\"></span>" +
"</div>";
divItem.innerHTML += "<div class=\"line2\" style=\"color: red;\" id=\"overview-gps-id-" + id + "\">kein GPS-Empfang</div>";
divItem.innerHTML += "<div class=\"line3\" id=\"overview-update-id-" + id + "\">Letzte Werte: vor " + timeCalculation(positionItem["Recievedtime"], "difftext") + "</div>";
return divItem;
}
function update_pannels_admin() {
var testadmin = new XMLHttpRequest();
testadmin.onreadystatechange = parseAjaxPannelAdmin;
testadmin.open("GET", "/admin", true);
testadmin.send();
}
function parseAjaxPannelAdmin() {
if (this.readyState === 4 && this.status === 403) {
var html = "<h3>Login to Adminpannel</h3><form onsubmit='submitloginform();return false;'>";
html += "<div><span class='label'>Username:</span><input id='pannels_admin_name'></div>";
html += "<div><span class='label'>Passwort:</span><input type='password' id='pannels_admin_pass'></div>";
html += "<div><span class='login'><input type='submit'></span></div></form>";
document.getElementById("pannels_admin").innerHTML = html;
} else if (this.readyState === 4 && this.status === 200) {
document.getElementById("pannels_admin").innerHTML = "<a href='/admin/' target='_blank'>Adminpannel</a>";
}
}
function submitloginform() {
var adminlogin = new XMLHttpRequest();
adminlogin.onreadystatechange = parseAjaxLogin;
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));
}
function parseAjaxLogin() {
if (this.readyState === 4 && this.status === 200) {
update_pannels_admin();
}
}
}.Start();

View File

@ -1,18 +1,8 @@
setInterval(overlayrunner, 1000);
function overlayrunner() {
var ccount = new XMLHttpRequest();
ccount.onreadystatechange = parseAjaxCount;
ccount.open("GET", "/cameracount", true);
ccount.send();
var cdensity = new XMLHttpRequest();
cdensity.onreadystatechange = parseAjaxDensity;
cdensity.open("GET", "/crowdcount", true);
cdensity.send();
}
function parseAjaxCount() {
if (this.readyState === 4 && this.status === 200) {
var cameracounts = JSON.parse(this.responseText);
var OverlayObject = {
Start: function () {
return this;
},
_ParseAJAXCount: function (cameracounts) {
var camerastext = "";
for (var cameraid in cameracounts) {
if (cameracounts.hasOwnProperty(cameraid)) {
@ -27,12 +17,8 @@ function parseAjaxCount() {
}
}
document.getElementById("cameracount").innerHTML = camerastext;
}
}
function parseAjaxDensity() {
if (this.readyState === 4 && this.status === 200) {
var cameradensy = JSON.parse(this.responseText);
},
_ParseAJAXDensity: function (cameradensy) {
var densystext = "";
for (var densyid in cameradensy) {
if (cameradensy.hasOwnProperty(densyid)) {
@ -46,4 +32,4 @@ function parseAjaxDensity() {
}
document.getElementById("crwoddensy").innerHTML = densystext;
}
}
}.Start();