Compare commits
17 Commits
master
...
29-laufweg
Author | SHA1 | Date | |
---|---|---|---|
abc48e5011 | |||
8ff0d679d9 | |||
fcb73810fd | |||
aa9c667d03 | |||
1e4c2db716 | |||
c5ff258793 | |||
85b309cbb0 | |||
fb2c98219a | |||
c052c57b7e | |||
3309972d71 | |||
6702c6392c | |||
47fe56304f | |||
410f3e9f81 | |||
df7e4f2044 | |||
00b228c008 | |||
e90bd678c1 | |||
f67d1b465c |
11
.github/workflows/dotnetcore.yml
vendored
11
.github/workflows/dotnetcore.yml
vendored
@ -28,7 +28,7 @@ jobs:
|
||||
working-directory: ../map-project/Lora-Map
|
||||
|
||||
- name: Create deb files
|
||||
if: success()
|
||||
if: ${{ success() && github.event.ref == 'refs/heads/master' }}
|
||||
run: |
|
||||
mkdir ../../../Builds
|
||||
chmod oug+x make-deb.sh
|
||||
@ -38,7 +38,7 @@ jobs:
|
||||
working-directory: ../map-project/Lora-Map/Lora-Map/dpkg
|
||||
|
||||
- name: Create release
|
||||
if: success()
|
||||
if: ${{ success() && github.event.ref == 'refs/heads/master' }}
|
||||
id: nightly_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
@ -51,7 +51,7 @@ jobs:
|
||||
prerelease: true
|
||||
|
||||
- name: Upload release asset amd64
|
||||
if: success()
|
||||
if: ${{ success() && github.event.ref == 'refs/heads/master' }}
|
||||
id: upload-release-asset-amd64
|
||||
uses: actions/upload-release-asset@v1.0.1
|
||||
env:
|
||||
@ -63,7 +63,7 @@ jobs:
|
||||
asset_content_type: application/x-deb
|
||||
|
||||
- name: Upload release asset armhf
|
||||
if: success()
|
||||
if: ${{ success() && github.event.ref == 'refs/heads/master' }}
|
||||
id: upload-release-asset-armhf
|
||||
uses: actions/upload-release-asset@v1.0.1
|
||||
env:
|
||||
@ -77,6 +77,7 @@ jobs:
|
||||
docker:
|
||||
name: Build and push dockerfile
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.ref == 'refs/heads/master' }}
|
||||
steps:
|
||||
- name: Checkout parent project with dependencys
|
||||
uses: actions/checkout@v1
|
||||
@ -86,10 +87,12 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Checkout last versions
|
||||
if: success()
|
||||
run: git -C Lora-Map checkout --progress --force ${{ github.sha }}
|
||||
working-directory: ../map-project
|
||||
|
||||
- name: Docker build
|
||||
if: success()
|
||||
id: docker_build
|
||||
run: |
|
||||
DOCKERTAG=$(date +%Y%m%d%H%M%S)
|
||||
|
30
CHANGELOG.md
30
CHANGELOG.md
@ -1,5 +1,35 @@
|
||||
# Changelogs
|
||||
|
||||
## 1.3.2 - Laufwege Visualisieren
|
||||
### New Features
|
||||
* Add posibility to make the past of a marker visible
|
||||
* Validating the input of Json, against defined models and only parse them if the match
|
||||
* Remove dublicated packets and if a correct one gets in replace the metadata of position
|
||||
* Notify other Objects when Settings are changed.
|
||||
### Bugfixes
|
||||
* If the settings are changed while collecting weather, ignore the exception
|
||||
* Fixing encoding problems in SVG
|
||||
* Fixing overlay with icon editor to be on the correct place at the screen
|
||||
* Coreccting the imagesize in the admin menu for SVG
|
||||
* Fixing a bug when open the nameseditor directly after start that images are not created
|
||||
### Changes
|
||||
* Refactoring
|
||||
* Change the SVG link to the correct array behavour
|
||||
* Used the new methods of AWebserverDataBackend
|
||||
* Run Github Actions on every commit, at least compiling the code for checking
|
||||
* Update leaflet to 1.7.1
|
||||
|
||||
## 1.3.1 - Refactory is the king
|
||||
### New Features
|
||||
* Make a SVG Generator and not modify the SVG on the fly
|
||||
* Split the js files on the admin pannel
|
||||
* add a swagger file
|
||||
### Bugfixes
|
||||
### Changes
|
||||
* Refactoring
|
||||
* Update the Manual a bit
|
||||
* Push to netcore 3.1
|
||||
|
||||
## 1.3.0 - New Gateway
|
||||
### New Features
|
||||
* Implement Lora-Gateway-Data 1.1.0 Format
|
||||
|
@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29519.87
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lora-Map_Core", "Lora-Map\Lora-Map.csproj", "{78136B15-FF0B-4DCE-94CA-1D6148DEA232}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lora-Map", "Lora-Map\Lora-Map.csproj", "{78136B15-FF0B-4DCE-94CA-1D6148DEA232}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7DD32F31-ACB0-4F5E-B3D8-78564A83ACEF}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
@ -55,11 +55,11 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="../CHANGELOG.md" />
|
||||
<Content Include="../CONTRIBUTING.md" />
|
||||
<Content Include="../LICENSE" />
|
||||
<Content Include="../README.md" />
|
||||
<Content Include="../map-swagger.yml" />
|
||||
<Content Include="../.github/workflows/dotnetcore.yml" />
|
||||
<Content Include="../CONTRIBUTING.md" />
|
||||
<Content Include="../LICENSE" />
|
||||
<Content Include="../README.md" />
|
||||
<Content Include="../map-swagger.yml" />
|
||||
<Content Include="../.github/workflows/dotnetcore.yml" />
|
||||
<Content Include="../doc/Manual.md" />
|
||||
</ItemGroup>
|
||||
|
||||
@ -196,6 +196,9 @@
|
||||
<None Update="resources\js\leaflet\leaflet.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="resources\js\leaflet\leaflet.js.map">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="resources\js\map.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
@ -2,16 +2,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
using BlubbFish.Utils;
|
||||
using BlubbFish.Utils.IoT.Bots;
|
||||
|
||||
using Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects;
|
||||
|
||||
using LitJson;
|
||||
|
||||
namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin {
|
||||
class AdminModel {
|
||||
public delegate void AdminEvent(Object sender, EventArgs e);
|
||||
#pragma warning disable 0067
|
||||
|
||||
//Supress never used warning (cause of reflection)
|
||||
#pragma warning disable 0067
|
||||
public event AdminEvent NamesUpdate;
|
||||
public event AdminEvent GeoUpdate;
|
||||
public event AdminEvent SettingsUpdate;
|
||||
@ -52,27 +57,33 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin {
|
||||
}
|
||||
}
|
||||
Console.WriteLine("200 - Send names.json " + cont.Request.Url.PathAndQuery);
|
||||
return Webserver.SendJsonResponse(ret, cont);
|
||||
return cont.SendStringResponse(JsonMapper.ToJson(ret));
|
||||
}
|
||||
} else if(cont.Request.HttpMethod == "PUT") {
|
||||
if(cont.Request.Url.AbsolutePath.Length > 16) {
|
||||
String part = cont.Request.Url.AbsolutePath[16..];
|
||||
if(this.datastorage.ContainsKey(part)) {
|
||||
return this.SetJsonFile(cont, "json/" + this.datastorage[part].Item1 + ".json", this.datastorage[part].Item2);
|
||||
return this.SetJsonFile(cont, part);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Webserver.SendFileResponse(cont);
|
||||
return cont.SendFileResponse();
|
||||
}
|
||||
|
||||
private Boolean SetJsonFile(HttpListenerContext cont, String filename, String updatenotifier) {
|
||||
private Boolean SetJsonFile(HttpListenerContext cont, String part) {
|
||||
StreamReader reader = new StreamReader(cont.Request.InputStream, cont.Request.ContentEncoding);
|
||||
String filename = "json/" + this.datastorage[part].Item1 + ".json";
|
||||
String rawData = reader.ReadToEnd();
|
||||
cont.Request.InputStream.Close();
|
||||
reader.Close();
|
||||
try {
|
||||
_ = JsonMapper.ToObject(rawData);
|
||||
JsonData json = JsonMapper.ToObject(rawData);
|
||||
if(part == "name") {
|
||||
if(!NamesModel.CheckJson(json)) {
|
||||
throw new Exception("Check against model failed.");
|
||||
}
|
||||
}
|
||||
} catch (Exception) {
|
||||
Helper.WriteError("501 - Error recieving " + filename + ", no valid json " + cont.Request.Url.PathAndQuery);
|
||||
cont.Response.StatusCode = 501;
|
||||
@ -80,12 +91,12 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin {
|
||||
}
|
||||
File.WriteAllText(filename, rawData);
|
||||
Console.WriteLine("200 - PUT " + filename + " " + cont.Request.Url.PathAndQuery);
|
||||
this.GetEvent<AdminEvent>(updatenotifier)?.Invoke(this, new EventArgs());
|
||||
this.GetEvent<AdminEvent>(this.datastorage[part].Item2)?.Invoke(this, new EventArgs());
|
||||
return true;
|
||||
}
|
||||
|
||||
private Boolean Login(HttpListenerContext cont) {
|
||||
Dictionary<String, String> POST = Webserver.GetPostParams(cont.Request);
|
||||
Dictionary<String, String> POST = cont.Request.GetPostParams();
|
||||
if(POST.ContainsKey("user") && POST["user"] == this.settings["admin_user"] && POST.ContainsKey("pass") && POST["pass"] == this.settings["admin_pass"]) {
|
||||
Int64 sessionid;
|
||||
while(true) {
|
||||
|
99
Lora-Map/Model/JsonObjects/LoraData.cs
Normal file
99
Lora-Map/Model/JsonObjects/LoraData.cs
Normal file
@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
using LitJson;
|
||||
|
||||
namespace Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects {
|
||||
public class LoraData {
|
||||
#region mandatory field
|
||||
public Double BatteryLevel {
|
||||
get;
|
||||
}
|
||||
public Boolean CorrectInterface {
|
||||
get;
|
||||
}
|
||||
public LoraDataGps Gps {
|
||||
get;
|
||||
}
|
||||
public String Hash {
|
||||
get;
|
||||
}
|
||||
public String Name {
|
||||
get;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region optional field
|
||||
public DateTime Receivedtime {
|
||||
get;
|
||||
}
|
||||
public Double Rssi {
|
||||
get;
|
||||
}
|
||||
public Double Snr {
|
||||
get;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
public static Boolean CheckJson(JsonData json) =>
|
||||
json.ContainsKey("BatteryLevel") && (json["BatteryLevel"].IsDouble || json["BatteryLevel"].IsInt)
|
||||
&& json.ContainsKey("CorrectInterface") && json["CorrectInterface"].IsBoolean
|
||||
&& json.ContainsKey("Gps") && json["Gps"].IsObject
|
||||
&& LoraDataGps.CheckJson(json["Gps"])
|
||||
&& json.ContainsKey("Hash") && json["Hash"].IsString
|
||||
&& json.ContainsKey("Name") && json["Name"].IsString;
|
||||
|
||||
public LoraData(JsonData json) {
|
||||
//mandatory field
|
||||
this.BatteryLevel = json["BatteryLevel"].IsInt ? (Int32)json["BatteryLevel"] : (Double)json["BatteryLevel"];
|
||||
this.CorrectInterface = (Boolean)json["CorrectInterface"];
|
||||
this.Gps = new LoraDataGps(json["Gps"]);
|
||||
this.Hash = (String)json["Hash"];
|
||||
this.Name = (String)json["Name"];
|
||||
//optional field
|
||||
this.Rssi = json.ContainsKey("Rssi") && (json["Rssi"].IsDouble || json["Rssi"].IsInt) ? json["Rssi"].IsInt ? (Int32)json["Rssi"] : (Double)json["Rssi"] : 0;
|
||||
this.Snr = json.ContainsKey("Snr") && (json["Snr"].IsDouble || json["Snr"].IsInt) ? json["Snr"].IsInt ? (Int32)json["Snr"] : (Double)json["Snr"] : 0;
|
||||
this.Receivedtime = json.ContainsKey("Receivedtime") && json["Receivedtime"].IsString && DateTime.TryParse((String)json["Receivedtime"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime) ? updatetime.ToUniversalTime() : DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
|
||||
public class LoraDataGps {
|
||||
#region mandatory field
|
||||
public Double Latitude {
|
||||
get;
|
||||
}
|
||||
public Double Longitude {
|
||||
get;
|
||||
}
|
||||
public Boolean Fix {
|
||||
get;
|
||||
}
|
||||
public Double Height {
|
||||
get;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region optional field
|
||||
public Double Hdop {
|
||||
get;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static Boolean CheckJson(JsonData json) =>
|
||||
json.ContainsKey("Latitude") && (json["Latitude"].IsDouble || json["Latitude"].IsInt)
|
||||
&& json.ContainsKey("Longitude") && (json["Longitude"].IsDouble || json["Longitude"].IsInt)
|
||||
&& json.ContainsKey("Fix") && json["Fix"].IsBoolean
|
||||
&& json.ContainsKey("Height") && (json["Height"].IsDouble || json["Height"].IsInt);
|
||||
|
||||
public LoraDataGps(JsonData json) {
|
||||
//mandatory field
|
||||
this.Latitude = json["Latitude"].IsInt ? (Int32)json["Latitude"] : (Double)json["Latitude"];
|
||||
this.Longitude = json["Longitude"].IsInt ? (Int32)json["Longitude"] : (Double)json["Longitude"];
|
||||
this.Fix = (Boolean)json["Fix"];
|
||||
this.Height = json["Height"].IsInt ? (Int32)json["Height"] : (Double)json["Height"];
|
||||
//optional field
|
||||
this.Hdop = json.ContainsKey("Hdop") && (json["Hdop"].IsDouble || json["Hdop"].IsInt) ? json["Hdop"].IsInt ? (Int32)json["Hdop"] : (Double)json["Hdop"] : 0;
|
||||
}
|
||||
}
|
||||
}
|
149
Lora-Map/Model/JsonObjects/NamesModel.cs
Normal file
149
Lora-Map/Model/JsonObjects/NamesModel.cs
Normal file
@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BlubbFish.Utils;
|
||||
|
||||
using LitJson;
|
||||
|
||||
namespace Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects {
|
||||
public class NamesModel {
|
||||
public SortedDictionary<String, NamesModelData> Items {
|
||||
get;
|
||||
}
|
||||
|
||||
public static Boolean CheckJson(JsonData json) {
|
||||
if(!json.IsObject) {
|
||||
return false;
|
||||
}
|
||||
foreach(String item in json.Keys) {
|
||||
if(!NamesModelData.CheckJson(json[item])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public NamesModel() {
|
||||
this.Items = new SortedDictionary<String, NamesModelData>();
|
||||
JsonData json = this.LoadFromFile();
|
||||
if(json != null && CheckJson(json)) {
|
||||
foreach(String item in json.Keys) {
|
||||
this.Items.Add(item, new NamesModelData(json[item]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JsonData LoadFromFile() {
|
||||
try {
|
||||
if(!Directory.Exists("json")) {
|
||||
_ = Directory.CreateDirectory("json");
|
||||
}
|
||||
if(!File.Exists("json/names.json")) {
|
||||
File.WriteAllText("json/names.json", "{}");
|
||||
}
|
||||
return JsonMapper.ToObject(File.ReadAllText("json/names.json"));
|
||||
} catch {
|
||||
Helper.WriteError("Could not load json/names.json");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class NamesModelData {
|
||||
#region mandatory field
|
||||
public String Name {
|
||||
get;
|
||||
}
|
||||
public String Group {
|
||||
get;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region optional field
|
||||
public String Icon {
|
||||
get;
|
||||
}
|
||||
public NamesModelDataMarkerSvg MarkerSvg {
|
||||
get;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static Boolean CheckJson(JsonData json) =>
|
||||
json.ContainsKey("name") && json["name"].IsString
|
||||
&& json.ContainsKey("Group") && json["Group"].IsString;
|
||||
|
||||
public NamesModelData(JsonData json) {
|
||||
//mandatory field
|
||||
this.Name = (String)json["name"];
|
||||
this.Group = (String)json["Group"];
|
||||
//optional field
|
||||
this.MarkerSvg = json.ContainsKey("marker.svg") && json["marker.svg"].IsObject && NamesModelDataMarkerSvg.CheckJson(json["marker.svg"]) ? new NamesModelDataMarkerSvg(json["marker.svg"]) : null;
|
||||
this.Icon = json.ContainsKey("icon") && json["icon"].IsString ? (String)json["icon"] : null;
|
||||
}
|
||||
}
|
||||
|
||||
public class NamesModelDataMarkerSvg {
|
||||
#region optional field
|
||||
public NamesModelDataMarkerSvgPerson Person {
|
||||
get;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static Boolean CheckJson(JsonData json) =>
|
||||
json.ContainsKey("person") && json["person"].IsObject;
|
||||
|
||||
public NamesModelDataMarkerSvg(JsonData json) {
|
||||
//optional field
|
||||
#pragma warning disable IDE0021 // Ausdruckskörper für Konstruktoren verwenden
|
||||
this.Person = json.ContainsKey("person") && json["person"].IsObject && NamesModelDataMarkerSvgPerson.CheckJson(json["person"]) ? new NamesModelDataMarkerSvgPerson(json["person"]) : null;
|
||||
#pragma warning restore IDE0021 // Ausdruckskörper für Konstruktoren verwenden
|
||||
}
|
||||
}
|
||||
|
||||
public class NamesModelDataMarkerSvgPerson {
|
||||
#region mandatory field
|
||||
public String Funktion {
|
||||
get;
|
||||
}
|
||||
public String Organisation {
|
||||
get;
|
||||
}
|
||||
public String Rang {
|
||||
get;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region optional field
|
||||
public String Text {
|
||||
get;
|
||||
}
|
||||
public List<String> Typ {
|
||||
get;
|
||||
}
|
||||
|
||||
#endregion
|
||||
public static Boolean CheckJson(JsonData json) =>
|
||||
json.ContainsKey("org") && json["org"].IsString
|
||||
&& json.ContainsKey("funct") && json["funct"].IsString
|
||||
&& json.ContainsKey("rang") && json["rang"].IsString;
|
||||
|
||||
public NamesModelDataMarkerSvgPerson(JsonData json) {
|
||||
//mandatory field
|
||||
this.Organisation = (String)json["org"];
|
||||
this.Funktion = (String)json["funct"];
|
||||
this.Rang = (String)json["rang"];
|
||||
//optional field
|
||||
this.Text = json.ContainsKey("text") && json["text"].IsString ? (String)json["text"] : null;
|
||||
List<String> typs = new List<String>();
|
||||
if(json.ContainsKey("typ") && json["typ"].IsArray) {
|
||||
foreach(JsonData item in json["typ"]) {
|
||||
if(item.IsString) {
|
||||
typs.Add(item.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
this.Typ = typs;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using LitJson;
|
||||
|
||||
using Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects;
|
||||
|
||||
namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position {
|
||||
public class PositionAlarm : PositionItem {
|
||||
@ -9,24 +10,21 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position {
|
||||
|
||||
public List<DateTime> ButtonPressed => this.buttonhistory.Keys.ToList();
|
||||
|
||||
public PositionAlarm(JsonData json) : base(json, null) {
|
||||
public PositionAlarm(LoraData data) : base(data, null) {
|
||||
}
|
||||
|
||||
public override void Update(JsonData json) {
|
||||
base.Update(json);
|
||||
this.SetHistory(json);
|
||||
public override void Update(LoraData data) {
|
||||
base.Update(data);
|
||||
this.SetHistory(data);
|
||||
}
|
||||
|
||||
private void SetHistory(JsonData json) {
|
||||
if(json.ContainsKey("Hash") && json["Hash"].IsString) {
|
||||
String key = json["Hash"].ToString();
|
||||
if(!this.buttonhistory.ContainsValue(key)) {
|
||||
this.buttonhistory.Add(DateTime.UtcNow, key);
|
||||
if(this.buttonhistory.Count > 10) {
|
||||
_ = this.buttonhistory.Remove(this.buttonhistory.Keys.ToList().First());
|
||||
}
|
||||
private void SetHistory(LoraData data) {
|
||||
if(!this.buttonhistory.ContainsValue(data.Hash)) {
|
||||
this.buttonhistory.Add(DateTime.UtcNow, data.Hash);
|
||||
if(this.buttonhistory.Count > 10) {
|
||||
_ = this.buttonhistory.Remove(this.buttonhistory.Keys.ToList().First());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,19 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects;
|
||||
using Fraunhofer.Fit.IoT.LoraMap.Model.Svg;
|
||||
|
||||
using LitJson;
|
||||
|
||||
namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position {
|
||||
public class PositionItem {
|
||||
private Double _lastLat = 0;
|
||||
private Double _lastLon = 0;
|
||||
private readonly SortedDictionary<DateTime, Double[]> _history = new SortedDictionary<DateTime, Double[]>();
|
||||
private String _lastHash = "";
|
||||
private Boolean _isdublicate = false;
|
||||
private Double _historycounter = 0;
|
||||
private readonly Object lockHistory = new Object();
|
||||
|
||||
public Double Rssi { get; private set; }
|
||||
public Double Snr { get; private set; }
|
||||
@ -27,19 +32,21 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position {
|
||||
public String Icon { get; private set; }
|
||||
public String MenuIcon { get; private set; }
|
||||
public String Group { get; private set; }
|
||||
public List<Double[]> History => this._history.Values.ToList();
|
||||
|
||||
public PositionItem(JsonData json, JsonData marker) {
|
||||
this.Update(json);
|
||||
this.UpdateMarker(marker, GetId(json));
|
||||
public PositionItem(LoraData data, NamesModel marker) {
|
||||
this.Update(data);
|
||||
this.UpdateMarker(marker, data.Name);
|
||||
Settings.Instance.SettingsUpdate += this.UpdateSettings;
|
||||
}
|
||||
|
||||
public void UpdateMarker(JsonData marker, String id) {
|
||||
if(marker != null && marker.ContainsKey(id)) {
|
||||
this.Name = marker[id].ContainsKey("name") && marker[id]["name"].IsString ? (String)marker[id]["name"] : id;
|
||||
Tuple<String, String> icons = this.ParseIconConfig(marker[id]);
|
||||
public void UpdateMarker(NamesModel marker, String id) {
|
||||
if(marker.Items.ContainsKey(id)) {
|
||||
this.Name = marker.Items[id].Name;
|
||||
Tuple<String, String> icons = this.ParseIconConfig(marker.Items[id]);
|
||||
this.Icon = icons.Item1;
|
||||
this.MenuIcon = icons.Item2;
|
||||
this.Group = marker[id].ContainsKey("Group") && marker[id]["Group"].IsString ? (String)marker[id]["Group"] : "no";
|
||||
this.Group = marker.Items[id].Group;
|
||||
} else {
|
||||
this.Name = id;
|
||||
this.Icon = null;
|
||||
@ -47,44 +54,43 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position {
|
||||
}
|
||||
}
|
||||
|
||||
private Tuple<String, String> ParseIconConfig(JsonData marker) {
|
||||
private Tuple<String, String> ParseIconConfig(NamesModelData marker) {
|
||||
String icon = null;
|
||||
String menu = null;
|
||||
if(marker.ContainsKey("marker.svg") && marker["marker.svg"].IsObject) {
|
||||
icon = SVGMarker.ParseConfig(marker["marker.svg"], this.Name);
|
||||
if(marker["marker.svg"].ContainsKey("person") && marker["marker.svg"]["person"].IsObject) {
|
||||
menu = SVGPerson.ParseConfig(marker["marker.svg"]["person"]);
|
||||
if(marker.MarkerSvg != null) {
|
||||
icon = SVGMarker.ParseConfig(marker.MarkerSvg, this.Name);
|
||||
if(marker.MarkerSvg.Person != null) {
|
||||
menu = SVGPerson.ParseConfig(marker.MarkerSvg.Person);
|
||||
}
|
||||
} else if(marker.ContainsKey("icon") && marker["icon"].IsString) {
|
||||
icon = (String)marker["icon"];
|
||||
} else if(marker.Icon != null) {
|
||||
icon = marker.Icon;
|
||||
}
|
||||
return new Tuple<String, String>(icon, menu);
|
||||
}
|
||||
|
||||
public static Boolean CheckJson(JsonData json) =>
|
||||
json.ContainsKey("BatteryLevel") && (json["BatteryLevel"].IsDouble || json["BatteryLevel"].IsInt)
|
||||
&& json.ContainsKey("Gps") && json["Gps"].IsObject
|
||||
&& json["Gps"].ContainsKey("Latitude") && (json["Gps"]["Latitude"].IsDouble || json["Gps"]["Latitude"].IsInt)
|
||||
&& json["Gps"].ContainsKey("Longitude") && (json["Gps"]["Longitude"].IsDouble || json["Gps"]["Longitude"].IsInt)
|
||||
&& json["Gps"].ContainsKey("Fix") && json["Gps"]["Fix"].IsBoolean
|
||||
&& json["Gps"].ContainsKey("Height") && (json["Gps"]["Height"].IsDouble || json["Gps"]["Height"].IsInt)
|
||||
&& json.ContainsKey("Name") && json["Name"].IsString;
|
||||
|
||||
public static String GetId(JsonData json) => (String)json["Name"];
|
||||
|
||||
public virtual void Update(JsonData json) {
|
||||
this.Rssi = json.ContainsKey("Rssi") && (json["Rssi"].IsDouble || json["Rssi"].IsInt) && Double.TryParse(json["Rssi"].ToString(), out Double rssi) ? rssi : 0;
|
||||
this.Snr = json.ContainsKey("Snr") && (json["Snr"].IsDouble || json["Snr"].IsInt) && Double.TryParse(json["Snr"].ToString(), out Double snr) ? snr : 0;
|
||||
this.Lorarecievedtime = json.ContainsKey("Receivedtime") && json["Receivedtime"].IsString && DateTime.TryParse((String)json["Receivedtime"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime) ? updatetime.ToUniversalTime() : DateTime.UtcNow;
|
||||
public virtual void Update(LoraData data) {
|
||||
this._isdublicate = false;
|
||||
if(data.Hash == this._lastHash) {
|
||||
if(!data.CorrectInterface) {
|
||||
Console.WriteLine("dublicate-Paket, reomove wrong reciever!");
|
||||
return;
|
||||
}
|
||||
this._isdublicate = true;
|
||||
Console.WriteLine("dublicate-Paket!");
|
||||
}
|
||||
this._lastHash = data.Hash;
|
||||
this.Rssi = data.Rssi;
|
||||
this.Snr = data.Snr;
|
||||
this.Lorarecievedtime = data.Receivedtime;
|
||||
this.Recievedtime = DateTime.UtcNow;
|
||||
this.Battery = Math.Round(json["BatteryLevel"].IsInt ? (Int32)json["BatteryLevel"] : (Double)json["BatteryLevel"], 2);
|
||||
this.Battery = Math.Round(data.BatteryLevel, 2);
|
||||
this.Batterysimple = this.Battery < 3.44 ? 0 : this.Battery < 3.53 ? 1 : this.Battery < 3.6525 ? 2 : this.Battery < 3.8825 ? 3 : 4;
|
||||
|
||||
this.Latitude = json["Gps"]["Latitude"].IsInt ? (Int32)json["Gps"]["Latitude"] : (Double)json["Gps"]["Latitude"];
|
||||
this.Longitude = json["Gps"]["Longitude"].IsInt ? (Int32)json["Gps"]["Longitude"] : (Double)json["Gps"]["Longitude"];
|
||||
this.Fix = (Boolean)json["Gps"]["Fix"];
|
||||
this.Height = json["Gps"]["Height"].IsInt ? (Int32)json["Gps"]["Height"] : (Double)json["Gps"]["Height"];
|
||||
this.Hdop = json["Gps"].ContainsKey("Hdop") && (json["Gps"]["Hdop"].IsDouble || json["Gps"]["Hdop"].IsInt) && Double.TryParse(json["Gps"]["Hdop"].ToString(), out Double hdop) ? hdop : 0;
|
||||
this.Latitude = data.Gps.Latitude;
|
||||
this.Longitude = data.Gps.Longitude;
|
||||
this.Fix = data.Gps.Fix;
|
||||
this.Height = data.Gps.Height;
|
||||
this.Hdop = data.Gps.Hdop;
|
||||
|
||||
if(!this.Fix) {
|
||||
this.Latitude = this._lastLat;
|
||||
@ -93,10 +99,46 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position {
|
||||
this._lastLat = this.Latitude;
|
||||
this._lastLon = this.Longitude;
|
||||
this.Lastgpspostime = DateTime.UtcNow;
|
||||
if(!this._isdublicate) {
|
||||
this.StoreHistory();
|
||||
}
|
||||
}
|
||||
this.UTM = new UTMData(this.Latitude, this.Longitude);
|
||||
}
|
||||
|
||||
|
||||
private void StoreHistory() {
|
||||
lock(this.lockHistory) {
|
||||
if(Settings.Instance.Internal.History.Enabled) {
|
||||
if(Settings.Instance.Internal.History.Amount != 0 && this._history.Count > Settings.Instance.Internal.History.Amount) {
|
||||
_ = this._history.Remove(this._history.Keys.ToList().First());
|
||||
}
|
||||
if(Settings.Instance.Internal.History.Time != 0) {
|
||||
List<DateTime> removeCandidates = new List<DateTime>();
|
||||
DateTime now = DateTime.UtcNow;
|
||||
foreach(KeyValuePair<DateTime, Double[]> item in this._history) {
|
||||
if((now - item.Key).TotalSeconds > Settings.Instance.Internal.History.Time) {
|
||||
removeCandidates.Add(item.Key);
|
||||
}
|
||||
}
|
||||
if(removeCandidates.Count > 0) {
|
||||
foreach(DateTime item in removeCandidates) {
|
||||
_ = this._history.Remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!this._history.ContainsKey(this.Recievedtime)) {
|
||||
this._history.Add(this.Recievedtime, new Double[] { this.Latitude, this.Longitude, this._historycounter++ });
|
||||
}
|
||||
} else {
|
||||
this._history.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSettings(Object sender, EventArgs e) {
|
||||
lock(this.lockHistory) {
|
||||
this._history.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using BlubbFish.Utils;
|
||||
|
||||
using Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects;
|
||||
|
||||
using LitJson;
|
||||
|
||||
namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position {
|
||||
public class PositionModel : OwnSingeton<PositionModel> {
|
||||
private readonly Object lockData = new Object();
|
||||
private readonly Object lockPanic = new Object();
|
||||
private JsonData marker;
|
||||
private readonly Object lockAlarm = new Object();
|
||||
private NamesModel marker;
|
||||
|
||||
public SortedDictionary<String, PositionItem> Positions {
|
||||
get; private set;
|
||||
@ -23,27 +24,25 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position {
|
||||
protected PositionModel() {
|
||||
this.Positions = new SortedDictionary<String, PositionItem>();
|
||||
this.Alarms = new SortedDictionary<String, PositionAlarm>();
|
||||
this.CheckJsonFile();
|
||||
this.marker = JsonMapper.ToObject(File.ReadAllText("json/names.json"));
|
||||
|
||||
this.marker = new NamesModel();
|
||||
}
|
||||
|
||||
public void ParseMqttJson(JsonData mqtt, String from) {
|
||||
if((from.Contains("lora/data") || from.Contains("lora/panic")) && PositionItem.CheckJson(mqtt)) {
|
||||
String name = PositionItem.GetId(mqtt);
|
||||
if((from.Contains("lora/data") || from.Contains("lora/panic")) && LoraData.CheckJson(mqtt)) {
|
||||
LoraData data = new LoraData(mqtt);
|
||||
lock(this.lockData) {
|
||||
if(this.Positions.ContainsKey(name)) {
|
||||
this.Positions[name].Update(mqtt);
|
||||
if(this.Positions.ContainsKey(data.Name)) {
|
||||
this.Positions[data.Name].Update(data);
|
||||
} else {
|
||||
this.Positions.Add(name, new PositionItem(mqtt, this.marker));
|
||||
this.Positions.Add(data.Name, new PositionItem(data, this.marker));
|
||||
}
|
||||
}
|
||||
if(from.Contains("lora/panic")) {
|
||||
lock(this.lockPanic) {
|
||||
if(this.Alarms.ContainsKey(name)) {
|
||||
this.Alarms[name].Update(mqtt);
|
||||
lock(this.lockAlarm) {
|
||||
if(this.Alarms.ContainsKey(data.Name)) {
|
||||
this.Alarms[data.Name].Update(data);
|
||||
} else {
|
||||
this.Alarms.Add(name, new PositionAlarm(mqtt));
|
||||
this.Alarms.Add(data.Name, new PositionAlarm(data));
|
||||
}
|
||||
}
|
||||
Console.WriteLine("PANIC erhalten!");
|
||||
@ -53,21 +52,11 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Position {
|
||||
}
|
||||
|
||||
public void ReloadNames(Object sender, EventArgs e) {
|
||||
this.CheckJsonFile();
|
||||
this.marker = JsonMapper.ToObject(File.ReadAllText("json/names.json"));
|
||||
this.marker = new NamesModel();
|
||||
foreach(KeyValuePair<String, PositionItem> item in this.Positions) {
|
||||
item.Value.UpdateMarker(this.marker, item.Key);
|
||||
}
|
||||
Console.WriteLine("Namen und Icons aktualisiert!");
|
||||
}
|
||||
|
||||
private void CheckJsonFile() {
|
||||
if(!Directory.Exists("json")) {
|
||||
_ = Directory.CreateDirectory("json");
|
||||
}
|
||||
if(!File.Exists("json/names.json")) {
|
||||
File.WriteAllText("json/names.json", "{}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,25 +25,27 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Sensor {
|
||||
|
||||
private void BackGroundRunner() {
|
||||
while(this.backgroundrunnerAlive) {
|
||||
List<Warning> ret = new List<Warning>();
|
||||
foreach(Int32 item in Settings.Instance.Internal.WeatherCellIDs) {
|
||||
try {
|
||||
JsonData json = this.webrequests.GetJson("https://maps.dwd.de/geoserver/wfs?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&typeName=dwd:Warnungen_Gemeinden&outputFormat=application/json&cql_filter=WARNCELLID=" + item);
|
||||
if (json.ContainsKey("features") && json["features"].IsArray && json["features"].Count > 0) {
|
||||
foreach (JsonData warning in json["features"]) {
|
||||
try {
|
||||
ret.Add(new Warning(warning));
|
||||
} catch { }
|
||||
try {
|
||||
List<Warning> ret = new List<Warning>();
|
||||
foreach(Int32 item in Settings.Instance.Internal.WeatherCellIDs) {
|
||||
try {
|
||||
JsonData json = this.webrequests.GetJson("https://maps.dwd.de/geoserver/wfs?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&typeName=dwd:Warnungen_Gemeinden&outputFormat=application/json&cql_filter=WARNCELLID=" + item);
|
||||
if(json.ContainsKey("features") && json["features"].IsArray && json["features"].Count > 0) {
|
||||
foreach(JsonData warning in json["features"]) {
|
||||
try {
|
||||
ret.Add(new Warning(warning));
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
this.Warnungen = ret;
|
||||
for (Int32 i = 0; i < 1000; i++) {
|
||||
if (this.backgroundrunnerAlive) {
|
||||
Thread.Sleep(60);
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
this.Warnungen = ret;
|
||||
for(Int32 i = 0; i < 1000; i++) {
|
||||
if(this.backgroundrunnerAlive) {
|
||||
Thread.Sleep(60);
|
||||
}
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,12 @@ using System.IO;
|
||||
|
||||
namespace Fraunhofer.Fit.IoT.LoraMap.Model {
|
||||
public class Settings : OwnSingeton<Settings> {
|
||||
|
||||
private Int32 gridradius;
|
||||
|
||||
public delegate void SettingsEvent(Object sender, EventArgs e);
|
||||
public event SettingsEvent SettingsUpdate;
|
||||
|
||||
|
||||
public PublicSettings External {
|
||||
get; set;
|
||||
}
|
||||
@ -124,9 +127,22 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model {
|
||||
}
|
||||
this.External.Sensors = sensors;
|
||||
}
|
||||
if(json.ContainsKey("History") && json["History"].IsObject) {
|
||||
if(json["History"].ContainsKey("enabled") && json["History"]["enabled"].IsBoolean) {
|
||||
this.Internal.History.Enabled = (Boolean)json["History"]["enabled"];
|
||||
}
|
||||
if(this.Internal.History.Enabled) {
|
||||
this.Internal.History.Time = json["History"].ContainsKey("time") && json["History"]["time"].IsInt ? (Int32)json["History"]["time"] : 0;
|
||||
this.Internal.History.Amount = json["History"].ContainsKey("amount") && json["History"]["amount"].IsInt ? (Int32)json["History"]["amount"] : 0;
|
||||
} else {
|
||||
this.Internal.History.Amount = 0;
|
||||
this.Internal.History.Time = 0;
|
||||
}
|
||||
}
|
||||
this.gridradius = json.ContainsKey("GridRadius") && json["GridRadius"].IsInt && this.External.Startloclat != 0 && this.External.Startloclon != 0 ? (Int32)json["GridRadius"] : 0;
|
||||
this.GenerateGrid();
|
||||
this.FindMapLayer();
|
||||
this.SettingsUpdate?.Invoke(this, new EventArgs());
|
||||
}
|
||||
|
||||
private void ParseGeoJson() {
|
||||
@ -294,6 +310,18 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model {
|
||||
}
|
||||
}
|
||||
|
||||
public class History {
|
||||
public Boolean Enabled {
|
||||
get; set;
|
||||
} = false;
|
||||
public Int32 Time {
|
||||
get; set;
|
||||
} = 0;
|
||||
public Int32 Amount {
|
||||
get; set;
|
||||
} = 0;
|
||||
}
|
||||
|
||||
public class PublicSettings {
|
||||
public Double Startloclat {
|
||||
get; set;
|
||||
@ -323,6 +351,9 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model {
|
||||
|
||||
public class PrivateSettings {
|
||||
public List<Int32> WeatherCellIDs { get; set; } = new List<Int32>();
|
||||
public History History {
|
||||
get; set;
|
||||
} = new History();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,13 +72,15 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
#endregion
|
||||
}
|
||||
|
||||
protected static String DictionaryConfigToString(Dictionary<String, String> config) {
|
||||
protected static String DictionaryConfigToString(Dictionary<String, List<String>> config) {
|
||||
String query = "";
|
||||
if(config.Count > 0) {
|
||||
query += "?";
|
||||
List<String> queryparts = new List<String>();
|
||||
foreach(KeyValuePair<String, String> item in config) {
|
||||
queryparts.Add(HttpUtility.UrlEncode(item.Key) + "=" + HttpUtility.UrlEncode(item.Value));
|
||||
foreach(KeyValuePair<String, List<String>> items in config) {
|
||||
foreach(String item in items.Value) {
|
||||
queryparts.Add(items.Key + "=" + HttpUtility.UrlEncode(item));
|
||||
}
|
||||
}
|
||||
query += String.Join("&", queryparts);
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
|
||||
using LitJson;
|
||||
using Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects;
|
||||
|
||||
namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
public class SVGMarker : SVGFile {
|
||||
@ -12,7 +12,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
|
||||
public SVGMarker(String query) : base(query, 86, 121.25, new List<Double>() { 0, 0, 86, 121.25 }) => this.css.Add("#marker-name tspan {\n font-size: 20px;\n font-family: DIN1451;\n}");
|
||||
|
||||
public static String ParseConfig(JsonData json, String name) => "api/svg/marker.svg" + DictionaryConfigToString(GenerateConfig(json, name));
|
||||
public static String ParseConfig(NamesModelDataMarkerSvg json, String name) => "api/svg/marker.svg" + DictionaryConfigToString(GenerateConfig(json, name));
|
||||
|
||||
protected override void ParseParams() {
|
||||
String[] parts = this.query.Split('&');
|
||||
@ -21,7 +21,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
if(keyvalue.Length == 2) {
|
||||
switch(keyvalue[0].ToLower()) {
|
||||
case "name":
|
||||
this.name = keyvalue[1];
|
||||
this.name = HttpUtility.UrlDecode(keyvalue[1]);
|
||||
break;
|
||||
case "icon":
|
||||
this.icon = keyvalue[1].ToLower();
|
||||
@ -31,14 +31,14 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<String, String> GenerateConfig(JsonData json, String name) {
|
||||
Dictionary<String, String> config = new Dictionary<String, String>();
|
||||
public static Dictionary<String, List<String>> GenerateConfig(NamesModelDataMarkerSvg json, String name) {
|
||||
Dictionary<String, List<String>> config = new Dictionary<String, List<String>>();
|
||||
if(name != "") {
|
||||
config.Add("name", name);
|
||||
config.Add("name", new List<String>() { name });
|
||||
}
|
||||
if(json.ContainsKey("person") && json["person"].IsObject) {
|
||||
config.Add("icon", "person");
|
||||
Dictionary<String, String> personconfig = SVGPerson.GenerateConfig(json["person"]);
|
||||
if(json.Person != null) {
|
||||
config.Add("icon", new List<String>() { "person" });
|
||||
Dictionary<String, List<String>> personconfig = SVGPerson.GenerateConfig(json.Person);
|
||||
personconfig.ToList().ForEach(x => config.Add(x.Key, x.Value));
|
||||
}
|
||||
return config;
|
||||
@ -52,7 +52,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
svg += "</g>\n";
|
||||
|
||||
svg += "<g inkscape:groupmode=\"layer\" id=\"marker-name\" inkscape:label=\"Name\">\n";
|
||||
svg += $"<text><tspan x=\"5\" y=\"20\" id=\"marker-name-text\">{this.name}</tspan></text>\n";
|
||||
svg += $"<text><tspan x=\"5\" y=\"20\" id=\"marker-name-text\">{HttpUtility.HtmlEncode(this.name)}</tspan></text>\n";
|
||||
svg += "</g>\n";
|
||||
|
||||
if(this.icon == "person") {
|
||||
|
@ -2,8 +2,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
using LitJson;
|
||||
using Fraunhofer.Fit.IoT.LoraMap.Model.JsonObjects;
|
||||
|
||||
namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
public class SVGPerson : SVGFile {
|
||||
@ -11,7 +12,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
private String function;
|
||||
private String rang;
|
||||
private String text;
|
||||
private String[] typs;
|
||||
private readonly List<String> typs = new List<String>();
|
||||
|
||||
|
||||
|
||||
@ -23,7 +24,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
this.css.Add("#person-layer-typ line {\n stroke-width: 3px;\n stroke: black;\n}");
|
||||
}
|
||||
|
||||
public static String ParseConfig(JsonData json) => "api/svg/person.svg" + DictionaryConfigToString(GenerateConfig(json));
|
||||
public static String ParseConfig(NamesModelDataMarkerSvgPerson json) => "api/svg/person.svg" + DictionaryConfigToString(GenerateConfig(json));
|
||||
|
||||
protected override void ParseParams() {
|
||||
String[] parts = this.query.Split('&');
|
||||
@ -41,38 +42,27 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
this.rang = keyvalue[1].ToLower();
|
||||
break;
|
||||
case "person-text":
|
||||
this.text = keyvalue[1];
|
||||
this.text = HttpUtility.UrlDecode(keyvalue[1]);
|
||||
break;
|
||||
case "person-typ":
|
||||
this.typs = keyvalue[1].ToLower().Split(",");
|
||||
case "person-typ[]":
|
||||
this.typs.Add(HttpUtility.UrlDecode(keyvalue[1]).ToLower());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<String, String> GenerateConfig(JsonData json) {
|
||||
Dictionary<String, String> config = new Dictionary<String, String>();
|
||||
if(json.ContainsKey("org") && json["org"].IsString) {
|
||||
config.Add("person-org", json["org"].ToString());
|
||||
public static Dictionary<String, List<String>> GenerateConfig(NamesModelDataMarkerSvgPerson json) {
|
||||
Dictionary<String, List<String>> config = new Dictionary<String, List<String>> {
|
||||
{ "person-org", new List<String>() { json.Organisation } },
|
||||
{ "person-funct", new List<String>() { json.Funktion } },
|
||||
{ "person-rang", new List<String>() { json.Rang } }
|
||||
};
|
||||
if(json.Text != null) {
|
||||
config.Add("person-text", new List<String>() { json.Text });
|
||||
}
|
||||
if(json.ContainsKey("funct") && json["funct"].IsString) {
|
||||
config.Add("person-funct", json["funct"].ToString());
|
||||
}
|
||||
if(json.ContainsKey("rang") && json["rang"].IsString) {
|
||||
config.Add("person-rang", json["rang"].ToString());
|
||||
}
|
||||
if(json.ContainsKey("text") && json["text"].IsString) {
|
||||
config.Add("person-text", json["text"].ToString());
|
||||
}
|
||||
if(json.ContainsKey("typ") && json["typ"].IsArray) {
|
||||
List<String> typs = new List<String>();
|
||||
foreach(JsonData item in json["person"]["typ"]) {
|
||||
if(item.IsString) {
|
||||
typs.Add(item.ToString());
|
||||
}
|
||||
}
|
||||
config.Add("person-typ", String.Join(",", typs));
|
||||
if(json.Typ.Count > 0) {
|
||||
config.Add("person-typ[]", json.Typ);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
@ -104,12 +94,11 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
svg += "</g>\n";
|
||||
svg += "</g>\n";
|
||||
}
|
||||
if(this.text != null || this.typs != null && this.typs.All(x => this.typlookup.ContainsKey(x))) {
|
||||
if(this.text != null || this.typs.Count > 0 && this.typs.All(x => this.typlookup.ContainsKey(x))) {
|
||||
svg += "<g inkscape:groupmode=\"layer\" id=\"person-layer-typ\" inkscape:label=\"Typ\">\n";
|
||||
if(this.text != null && this.typs == null) {
|
||||
svg += $"<text><tspan y=\"42\" x=\"0\" id=\"person-layer-typ-text\">{this.text}</tspan></text>\n";
|
||||
}
|
||||
if(this.text == null && this.typs != null && this.typs.All(x => this.typlookup.ContainsKey(x))) {
|
||||
if(this.text != null) {
|
||||
svg += $"<text><tspan y=\"42\" x=\"0\" id=\"person-layer-typ-text\">{HttpUtility.HtmlEncode(this.text)}</tspan></text>\n";
|
||||
} else if(this.typs.Count > 0 && this.typs.All(x => this.typlookup.ContainsKey(x))) {
|
||||
foreach(String typ in this.typs) {
|
||||
svg += $"<g id=\"person-layer-typ-{typ}\" inkscape:label=\"{this.typlookup[typ].Name}\">\n";
|
||||
foreach(Tuple<Double, Double, Double, Double> item in this.typlookup[typ].Lines) {
|
||||
|
@ -8,6 +8,8 @@ using BlubbFish.Utils;
|
||||
namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
public class SvgModel : OwnSingeton<SvgModel> {
|
||||
private readonly Dictionary<String, SVGFile> svgtable = new Dictionary<String, SVGFile>();
|
||||
private readonly Object lockSVG = new Object();
|
||||
|
||||
public Boolean ParseRequest(HttpListenerContext cont) {
|
||||
Byte[] svg = this.GetSvg(cont.Request.Url.PathAndQuery);
|
||||
if(svg.Length > 0) {
|
||||
@ -26,14 +28,16 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Svg {
|
||||
if(this.svgtable.ContainsKey(pathAndQuery)) {
|
||||
return Encoding.UTF8.GetBytes(this.svgtable[pathAndQuery].ToString());
|
||||
} else {
|
||||
if(pathAndQuery.StartsWith("/api/svg/marker.svg") && pathAndQuery.Contains("?")) {
|
||||
String query = pathAndQuery[(pathAndQuery.IndexOf('?') + 1)..];
|
||||
this.svgtable.Add(pathAndQuery, new SVGMarker(query));
|
||||
return Encoding.UTF8.GetBytes(this.svgtable[pathAndQuery].ToString());
|
||||
} else if(pathAndQuery.StartsWith("/api/svg/person.svg") && pathAndQuery.Contains("?")) {
|
||||
String query = pathAndQuery[(pathAndQuery.IndexOf('?') + 1)..];
|
||||
this.svgtable.Add(pathAndQuery, new SVGPerson(query));
|
||||
return Encoding.UTF8.GetBytes(this.svgtable[pathAndQuery].ToString());
|
||||
lock(this.lockSVG) {
|
||||
if(pathAndQuery.StartsWith("/api/svg/marker.svg") && pathAndQuery.Contains("?")) {
|
||||
String query = pathAndQuery[(pathAndQuery.IndexOf('?') + 1)..];
|
||||
this.svgtable.Add(pathAndQuery, new SVGMarker(query));
|
||||
return Encoding.UTF8.GetBytes(this.svgtable[pathAndQuery].ToString());
|
||||
} else if(pathAndQuery.StartsWith("/api/svg/person.svg") && pathAndQuery.Contains("?")) {
|
||||
String query = pathAndQuery[(pathAndQuery.IndexOf('?') + 1)..];
|
||||
this.svgtable.Add(pathAndQuery, new SVGPerson(query));
|
||||
return Encoding.UTF8.GetBytes(this.svgtable[pathAndQuery].ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Byte[0];
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
using BlubbFish.Utils;
|
||||
using BlubbFish.Utils.IoT.Bots;
|
||||
@ -17,7 +18,7 @@ using Fraunhofer.Fit.IoT.LoraMap.Model.Svg;
|
||||
using LitJson;
|
||||
|
||||
namespace Fraunhofer.Fit.IoT.LoraMap {
|
||||
class Server : Webserver {
|
||||
class Server : AWebserverDataBackend {
|
||||
private readonly SortedDictionary<String, Object> jsonapi = new SortedDictionary<String, Object>() {
|
||||
{ "camera", CameraModel.Instance },
|
||||
{ "position", PositionModel.Instance },
|
||||
@ -26,12 +27,13 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
|
||||
};
|
||||
private readonly AdminModel admin;
|
||||
|
||||
public Server(ADataBackend backend, Dictionary<String, String> settings) : base(backend, settings, null) {
|
||||
public Server(ADataBackend backend, Dictionary<String, String> settings) : base(backend, settings) {
|
||||
this.logger.SetPath(settings["loggingpath"]);
|
||||
this.admin = new AdminModel(settings);
|
||||
this.admin.SettingsUpdate += Settings.Instance.ReloadSettings;
|
||||
this.admin.GeoUpdate += Settings.Instance.ReloadGeo;
|
||||
this.admin.NamesUpdate += PositionModel.Instance.ReloadNames;
|
||||
this.StartDataBackend();
|
||||
this.StartListen();
|
||||
this.WaitForShutdown();
|
||||
this.Dispose();
|
||||
@ -59,23 +61,23 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
|
||||
ret.Add(part, this.jsonapi[part]);
|
||||
}
|
||||
}
|
||||
return SendJsonResponse(ret, cont);
|
||||
return cont.SendStringResponse(JsonMapper.ToJson(ret));
|
||||
}
|
||||
} else if(cont.Request.Url.AbsolutePath.StartsWith("/api/time")) {
|
||||
return SendJsonResponse(new Dictionary<String, DateTime>() { { "utc", DateTime.UtcNow } }, cont);
|
||||
return cont.SendStringResponse(JsonMapper.ToJson(new Dictionary<String, DateTime>() { { "utc", DateTime.UtcNow } }));
|
||||
} else if(cont.Request.Url.AbsolutePath.StartsWith("/api/svg/")) {
|
||||
return SvgModel.Instance.ParseRequest(cont);
|
||||
} else if(cont.Request.Url.PathAndQuery.StartsWith("/admin/")) {
|
||||
return this.admin.ParseReuqest(cont);
|
||||
} else if(cont.Request.Url.PathAndQuery.StartsWith("/maps/")) {
|
||||
return SendFileResponse(cont, "resources", false);
|
||||
return cont.SendFileResponse("resources", false);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
Helper.WriteError("SendWebserverResponse(): 500 - " + e.Message + "\n\n" + e.StackTrace);
|
||||
cont.Response.StatusCode = 500;
|
||||
return false;
|
||||
}
|
||||
return SendFileResponse(cont);
|
||||
return cont.SendFileResponse();
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
|
@ -69,7 +69,7 @@
|
||||
}
|
||||
|
||||
#iconeditor {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
@ -32,21 +32,21 @@
|
||||
if (Object.prototype.hasOwnProperty.call(query, "person-text")) {
|
||||
markerobj["person"]["text"] = query["person-text"];
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(query, "person-typ")) {
|
||||
if (Array.isArray(query["person-typ"])) {
|
||||
if (Object.prototype.hasOwnProperty.call(query, "person-typ[]")) {
|
||||
if (Array.isArray(query["person-typ[]"])) {
|
||||
markerobj["person"]["typ"] = new Array();
|
||||
for (var i in query["person-typ"]) {
|
||||
markerobj["person"]["typ"].push(query["person-typ"][i]);
|
||||
for (var i in query["person-typ[]"]) {
|
||||
markerobj["person"]["typ"].push(query["person-typ[]"][i]);
|
||||
}
|
||||
} else {
|
||||
markerobj["person"]["typ"] = new Array();
|
||||
markerobj["person"]["typ"].push(query["person-typ"]);
|
||||
markerobj["person"]["typ"].push(query["person-typ[]"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return markerobj;
|
||||
},
|
||||
ChangeLinkPreview: function (key, val) {
|
||||
ChangeLinkPreview: function (key, val, multiple) {
|
||||
var cur = this.SplitUrlIntoParts(document.getElementById("markerprev").data);
|
||||
var query = this.SplitQueryIntoObject(cur.query);
|
||||
if (typeof val === "object") {
|
||||
@ -71,13 +71,13 @@
|
||||
var html = title !== "" ? title + ": " : "";
|
||||
var onchange = "";
|
||||
if (!(typeof noonchange !== "undefined" && noonchange === true)) {
|
||||
var eventtext = "NamesEditor.ChangeLinkPreview(\"" + key + "\",this.selectedOptions);";
|
||||
var eventtext = "NamesEditor.ChangeLinkPreview(\"" + key + "\", this.selectedOptions, multiple);";
|
||||
if (typeof group !== "undefined" && group !== null) {
|
||||
eventtext += " document.getElementById(\"" + group + "\"+this.value).style.display = \"block\";'";
|
||||
}
|
||||
onchange = " onchange='" + eventtext + "'";
|
||||
}
|
||||
html += "<select" + onchange + (typeof muliple !== "undefined" && muliple !== null ? " multiple" : "") + ">";
|
||||
html += "<select" + onchange + (typeof muliple !== "undefined" && muliple === true ? " multiple" : "") + ">";
|
||||
if (typeof muliple === "undefined" || muliple === null) {
|
||||
html += "<option>---</option>";
|
||||
}
|
||||
@ -122,7 +122,7 @@
|
||||
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><img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> <object data='" + url + "' type='image/svg+xml' style='height:57px; 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>";
|
||||
@ -137,15 +137,15 @@
|
||||
var ie = document.createElement("div");
|
||||
ie.id = "iconeditor";
|
||||
ie.innerHTML = "<div class='innerbox'>" +
|
||||
"<div class='preview'><object id='markerprev' data='" + url + "' type='image/svg+xml' style='height:200px; width:200px;'></object></div>" +
|
||||
"<div class='preview'><object id='markerprev' data='" + url + "' type='image/svg+xml' style='height:226px; width:200px;'></object></div>" +
|
||||
"<div class='controls'>" +
|
||||
this.CreateSelectBox("Typ", "icon", query, { "person": "Person" }, null, "iconeditor-type-") + "<br>" +
|
||||
"<div id='iconeditor-type-person' style='display: " + (Object.prototype.hasOwnProperty.call(query, "icon") && query["icon"] === "person" ? "block" : "none") + ";'>" +
|
||||
this.CreateSelectBox("Organisation", "person-org", query, { "fw": "Feuerwehr", "thw": "Technisches Hilfswerk", "hilo": "Hilfsorganisationen, Bundeswehr", "fueh": "Einrichtungen der Führung", "pol": "Polizei, Bundespolizei, Zoll", "sonst": "Sonstige Einrichtungen der Gefahrenabwehr" }) + "<br>" +
|
||||
this.CreateSelectBox("Funktion", "person-funct", query, { "sonder": "Sonder", "fueh": "Führung" }) + "<br>" +
|
||||
this.CreateSelectBox("Rang", "person-rang", query, { "trupp": "Trupp", "grupp": "Gruppe", "zug": "Zug" }) + "<br>" +
|
||||
"Text: <input onchange='NamesEditor.ChangeLinkPreview(\"person-text\",this.value);' value='" + (Object.prototype.hasOwnProperty.call(query, "person-text") ? query["person-text"] : "") + "'><br>" +
|
||||
this.CreateSelectBox("Typ", "person-typ", query, { "loesch": "Brandbekämpfung/Löscheinsatz", "sani": "Rettungswesen, Sanitätswesen, Gesundheitswesen", "betreu": "Betreuung" }, true) + "<br>" +
|
||||
"Text: <input onchange='NamesEditor.ChangeLinkPreview(\"person-text\", this.value, false);' value='" + (Object.prototype.hasOwnProperty.call(query, "person-text") ? query["person-text"] : "") + "'><br>" +
|
||||
this.CreateSelectBox("Typ", "person-typ[]", query, { "loesch": "Brandbekämpfung/Löscheinsatz", "sani": "Rettungswesen, Sanitätswesen, Gesundheitswesen", "betreu": "Betreuung" }, true) + "<br>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"<div class='save'><button onclick='NamesEditor.SaveIconEditor(\"" + el.id + "\"); '>Schließen</botton></div>" +
|
||||
@ -157,10 +157,10 @@
|
||||
for (var id in queryobj) {
|
||||
if (Array.isArray(queryobj[id])) {
|
||||
for (var i in queryobj[id]) {
|
||||
query.push(encodeURIComponent(id) + "=" + encodeURIComponent(queryobj[id][i]));
|
||||
query.push(id + "=" + encodeURIComponent(queryobj[id][i]));
|
||||
}
|
||||
} else {
|
||||
query.push(encodeURIComponent(id) + "=" + encodeURIComponent(queryobj[id]));
|
||||
query.push(id + "=" + encodeURIComponent(queryobj[id]));
|
||||
}
|
||||
}
|
||||
return query.join("&");
|
||||
@ -183,11 +183,11 @@
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(markerobj["person"], "typ") && Array.isArray(markerobj["person"]["typ"])) {
|
||||
for (i in markerobj["person"]["typ"]) {
|
||||
url += "&person-typ=" + markerobj["person"]["typ"][i];
|
||||
url += "&person-typ[]=" + markerobj["person"]["typ"][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return "<object data='" + url + "' type='image/svg+xml' style='height:50px; width:50px;'></object>";
|
||||
return "<object data='" + url + "' type='image/svg+xml' style='height:57px; width:50px;'></object>";
|
||||
},
|
||||
ParseJson: function (namesconfig) {
|
||||
document.getElementById("content").innerHTML = "";
|
||||
@ -249,7 +249,7 @@
|
||||
},
|
||||
SaveIconEditor: function (id) {
|
||||
var cell = document.getElementById(id);
|
||||
cell.innerHTML = "<img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> <object data='" + document.getElementById("markerprev").data + "' type='image/svg+xml' style='height:50px; width:50px;'></object>";
|
||||
cell.innerHTML = "<img src='../icons/general/icon_edit.png' onclick='NamesEditor.IconEditor(this.parentNode)' class='pointer'> <object data='" + document.getElementById("markerprev").data + "' type='image/svg+xml' style='height:57px; width:50px;'></object>";
|
||||
cell.removeAttribute("id");
|
||||
document.getElementById("iconeditor").remove();
|
||||
},
|
||||
@ -269,7 +269,7 @@
|
||||
if (url === null) {
|
||||
el.innerHTML += "<td><img src='../js/leaflet/images/marker-icon.png'></td>";
|
||||
} else {
|
||||
el.innerHTML += "<td><object data='" + url + "' type='image/svg+xml' style='height:50px; width:50px;'></object></td>";
|
||||
el.innerHTML += "<td><object data='" + url + "' type='image/svg+xml' style='height:57px; 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>";
|
||||
|
@ -58,34 +58,38 @@
|
||||
"<td><img src='../icons/general/save.png' onclick='Settings.SaveRowSensor(this.parentNode.parentNode)' class='pointer'> <img src='../icons/general/remove.png' onclick='Settings.Abort(this.parentNode.parentNode)' class='pointer'></td>";
|
||||
},
|
||||
ParseJson: function (jsonsettings) {
|
||||
if (typeof jsonsettings.StartPos === "undefined") {
|
||||
if (!Object.prototype.hasOwnProperty.call(jsonsettings, "StartPos")) {
|
||||
jsonsettings.StartPos = { lat: 0, lon: 0 };
|
||||
}
|
||||
if (typeof jsonsettings.CellIds === "undefined") {
|
||||
if (!Object.prototype.hasOwnProperty.call(jsonsettings, "CellIds")) {
|
||||
jsonsettings.CellIds = [];
|
||||
}
|
||||
if (typeof jsonsettings.GridRadius === "undefined") {
|
||||
if (!Object.prototype.hasOwnProperty.call(jsonsettings, "GridRadius")) {
|
||||
jsonsettings.GridRadius = 1000;
|
||||
}
|
||||
if (typeof jsonsettings.FightDedection === "undefined") {
|
||||
if (!Object.prototype.hasOwnProperty.call(jsonsettings, "FightDedection")) {
|
||||
jsonsettings.FightDedection = [];
|
||||
}
|
||||
if (typeof jsonsettings.CrwodDensity === "undefined") {
|
||||
if (!Object.prototype.hasOwnProperty.call(jsonsettings, "CrwodDensity")) {
|
||||
jsonsettings.CrwodDensity = [];
|
||||
}
|
||||
if (typeof jsonsettings.Counting === "undefined") {
|
||||
if (!Object.prototype.hasOwnProperty.call(jsonsettings, "Counting")) {
|
||||
jsonsettings.Counting = [];
|
||||
}
|
||||
if (typeof jsonsettings.Sensors === "undefined") {
|
||||
if (!Object.prototype.hasOwnProperty.call(jsonsettings, "Sensors")) {
|
||||
jsonsettings.Sensors = [];
|
||||
}
|
||||
if (!Object.prototype.hasOwnProperty.call(jsonsettings, "History")) {
|
||||
jsonsettings.History = [];
|
||||
}
|
||||
var html = "<div id='settingseditor'><div class='title'>Einstellungen</div>";
|
||||
html += "<div class='startloc'>Startpunkt: <input value='" + jsonsettings.StartPos.lat + "' id='startlat'> Lat, <input value='" + jsonsettings.StartPos.lon + "' id='startlon'> Lon</div>";
|
||||
html += "<div class='wetterwarnings'>CellId's für DWD-Wetterwarnungen: <input value='" + jsonsettings.CellIds.join(";") + "' id='wetterids'> (Trennen durch \";\", <a href='https://www.dwd.de/DE/leistungen/opendata/help/warnungen/cap_warncellids_csv.html'>cap_warncellids_csv</a>)</div>";
|
||||
html += "<div class='gridradius'>Radius für das Grid um den Startpunkt: <input value='" + jsonsettings.GridRadius + "' id='gridrad'>m</div>";
|
||||
html += "<div class='fightdedection'>Fight Dedection Kameras: <br>" + this._renderFightDedection(jsonsettings.FightDedection) + "</div>";
|
||||
html += "<div class='crowddensity'>Crowd Density Kameras: <br>" + this._renderCrowdDensity(jsonsettings.CrwodDensity) + "</div>";
|
||||
html += "<div class='sensorsettings'>Sensors: <br>" + this._renderSensorSettings(jsonsettings.Sensors) + "</div>";
|
||||
html += "<div class='startloc'>Startpunkt: <input value='" + jsonsettings.StartPos.lat + "' id='startlat'> Lat, <input value='" + jsonsettings.StartPos.lon + "' id='startlon'> Lon</div><hr>";
|
||||
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><hr>";
|
||||
html += "<div class='gridradius'>Radius für das Grid um den Startpunkt: <input value='" + jsonsettings.GridRadius + "' id='gridrad'>m</div><hr>";
|
||||
html += "<div class='fightdedection'>Fight Dedection Kameras: <br>" + this._renderFightDedection(jsonsettings.FightDedection) + "</div><hr>";
|
||||
html += "<div class='crowddensity'>Crowd Density Kameras: <br>" + this._renderCrowdDensity(jsonsettings.CrwodDensity) + "</div><hr>";
|
||||
html += "<div class='sensorsettings'>Sensors: <br>" + this._renderSensorSettings(jsonsettings.Sensors) + "</div><hr>";
|
||||
html += "<div class='historysettings'>History: "+this._renderHistorySettings(jsonsettings.History)+"</div><hr>";
|
||||
html += "<div class='savesettings'><img src='../icons/general/save.png' onclick='Settings.Save()' class='pointer'></div>";
|
||||
document.getElementById("content").innerHTML = html + "</div>";
|
||||
},
|
||||
@ -159,6 +163,29 @@
|
||||
}
|
||||
ret.Sensors = sensorjson;
|
||||
|
||||
ret.History = {};
|
||||
if (document.getElementById("hist_yes").checked && !document.getElementById("hist_no").checked) {
|
||||
ret.History.enabled = true;
|
||||
var time = parseInt(document.getElementById("history_time").value);
|
||||
if (isNaN(time)) {
|
||||
time = 0;
|
||||
}
|
||||
var amount = parseInt(document.getElementById("history_amount").value);
|
||||
if (isNaN(amount)) {
|
||||
amount = 0;
|
||||
}
|
||||
if (time !== 0 && amount !== 0) {
|
||||
alert("History: Entweder Zeit oder Menge muss 0 sein.");
|
||||
return;
|
||||
}
|
||||
ret.History.time = time;
|
||||
ret.History.amount = amount;
|
||||
} else {
|
||||
ret.History.enabled = false;
|
||||
ret.History.time = 0;
|
||||
ret.History.amount = 0;
|
||||
}
|
||||
|
||||
var savesettings = new XMLHttpRequest();
|
||||
savesettings.onreadystatechange = function () {
|
||||
if (savesettings.readyState === 4) {
|
||||
@ -306,6 +333,20 @@
|
||||
ret += "</table>";
|
||||
return ret;
|
||||
},
|
||||
_renderHistorySettings: function (json) {
|
||||
if (!Object.prototype.hasOwnProperty.call(json, "enabled")) {
|
||||
json.enabled = false;
|
||||
}
|
||||
if (!Object.prototype.hasOwnProperty.call(json, "time")) {
|
||||
json.time = 0;
|
||||
}
|
||||
if (!Object.prototype.hasOwnProperty.call(json, "amount")) {
|
||||
json.amount = 0;
|
||||
}
|
||||
var html = "Aktiv: <fieldset style='border:none;'> <label for='hist_no'>Nein </label> <input onclick=\"document.getElementById('history_settings_details').style.display='none'\" type='radio' id='hist_no' name='hist_en' value='no' " + (json.enabled ? "" : "checked='checked'") + "> <label for='hist_yes'>Ja </label> <input onclick=\"document.getElementById('history_settings_details').style.display='block'\" type='radio' id='hist_yes' name='hist_en' value='yes' " + (json.enabled ? "checked='checked'" : "") + "> </fieldset>";
|
||||
html += "<span id='history_settings_details' style='display: " + (json.enabled ? "block" : "none") + "'>Zeit: <input type='number' id='history_time' value='" + json.time + "'>s, Menge: <input type='number' id='history_amount' value='" + json.amount +"'></span>"
|
||||
return html;
|
||||
},
|
||||
_renderSensorSettings: function (json) {
|
||||
var ret = "";
|
||||
ret += "<table id='sensortable' class='settingstable'>";
|
||||
@ -326,5 +367,5 @@
|
||||
ret += "<tfoot><tr><td></td><td></td><td></td><td></td><td><img src='../icons/general/add.png' onclick='Settings.AddSensor()' class='pointer'></td></tr></tfoot>";
|
||||
ret += "</table>";
|
||||
return ret;
|
||||
},
|
||||
}
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -25,6 +25,10 @@
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
/* Prevents IE11 from highlighting tiles in blue */
|
||||
.leaflet-tile::selection {
|
||||
background: transparent;
|
||||
}
|
||||
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
|
||||
.leaflet-safari .leaflet-tile {
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
@ -237,7 +241,8 @@
|
||||
|
||||
.leaflet-marker-icon.leaflet-interactive,
|
||||
.leaflet-image-layer.leaflet-interactive,
|
||||
.leaflet-pane > svg path.leaflet-interactive {
|
||||
.leaflet-pane > svg path.leaflet-interactive,
|
||||
svg.leaflet-image-layer.leaflet-interactive path {
|
||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||
pointer-events: auto;
|
||||
}
|
||||
@ -527,7 +532,7 @@
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper {
|
||||
zoom: 1;
|
||||
-ms-zoom: 1;
|
||||
}
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
width: 24px;
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -7,6 +7,7 @@
|
||||
_Markers: {},
|
||||
_Sensors: {},
|
||||
_SensorSettings: {},
|
||||
_History: {},
|
||||
/// public functions
|
||||
ChangeFilter: function (select) {
|
||||
this.VisibleMarkers = {};
|
||||
@ -53,6 +54,21 @@
|
||||
return this;
|
||||
},
|
||||
/// private functions
|
||||
_ClearHistory: function (key) {
|
||||
if (Object.prototype.hasOwnProperty.call(this._History, key)) {
|
||||
if (typeof this._History[key].Polyline === 'object') {
|
||||
this._History[key].Polyline.remove();
|
||||
delete this._History[key];
|
||||
}
|
||||
}
|
||||
},
|
||||
_CreateLatLonFromHist: function (key) {
|
||||
var latlngs = [];
|
||||
for (var i = 0; i < this._History[key].Items.length; i++) {
|
||||
latlngs.push([this._History[key].Items[i][0], this._History[key].Items[i][1]]);
|
||||
}
|
||||
return latlngs;
|
||||
},
|
||||
_ParseAJAXLoc: function (serverLocation) {
|
||||
this.LocationData = serverLocation;
|
||||
for (var key in this.LocationData) {
|
||||
@ -113,11 +129,16 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
if (positionItem.History.length > 0) {
|
||||
this._UpdateHistory(positionItem.History, key);
|
||||
} else {
|
||||
this._ClearHistory(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
MenuObject.UpdateStatus();
|
||||
MenuObject._Update_pannels_info();
|
||||
},
|
||||
MenuObject.UpdatePannelsInfo();
|
||||
},
|
||||
_ParseAJAXPanic: function (serverPanic) {
|
||||
this.PanicData = serverPanic;
|
||||
for (var id in this.PanicData) {
|
||||
@ -167,5 +188,38 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_UpdateHistory: function (History, key) {
|
||||
if (!Object.prototype.hasOwnProperty.call(this._History, key)) {
|
||||
this._History[key] = { Items: History };
|
||||
this._History[key].Polyline = L.polyline(this._CreateLatLonFromHist(key), { color: 'blue', weight: 2, bubblingMouseEvents: false, interactive: false }).addTo(MapObject.Map);
|
||||
}
|
||||
if (History[0][2] !== this._History[key].Items[0][2] || History[History.length - 1][2] !== this._History[key].Items[this._History[key].Items.length - 1][2]) {
|
||||
if (History[History.length - 1][2] !== this._History[key].Items[this._History[key].Items.length - 1][2]) {
|
||||
// Last element are different, so add element to the line
|
||||
for (var i = History.length - 1; i >= 0; i--) {
|
||||
if (History[i][2] === this._History[key].Items[this._History[key].Items.length - 1][2]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (var j = i + 1; j < History.length; j++) {
|
||||
this._History[key].Items.push(History[j]);
|
||||
}
|
||||
}
|
||||
if (History[0][2] !== this._History[key].Items[0][2]) {
|
||||
//First elemt are different, so delete element from the line
|
||||
var deletefirst = 0;
|
||||
for (var k = 0; k < this._History[key].Items.length; k++) {
|
||||
if (History[0][2] === this._History[key].Items[k][2]) {
|
||||
break;
|
||||
}
|
||||
deletefirst++;
|
||||
}
|
||||
for (var l = 0; l < deletefirst; l++) {
|
||||
this._History[key].Items.splice(0, 1);
|
||||
}
|
||||
}
|
||||
this._History[key].Polyline.setLatLngs(this._CreateLatLonFromHist(key));
|
||||
}
|
||||
}
|
||||
}.Start();
|
@ -69,6 +69,37 @@
|
||||
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));
|
||||
},
|
||||
UpdatePannelsInfo: function () {
|
||||
document.getElementById("pannels_info").innerHTML = "";
|
||||
if (Object.prototype.hasOwnProperty.call(MarkerObject.LocationData, this.statusToDevice)) {
|
||||
var positionItem = MarkerObject.LocationData[this.statusToDevice];
|
||||
var html = "<div class=\"name\">Name: <span class=\"bold\">" + positionItem["Name"] + "</span></div>";
|
||||
html += "<div class=\"batt\"><span class=\"bold\">Batterie:</span> " + positionItem["Battery"] + "V <img src=\"icons/akku/" + positionItem["Batterysimple"] + "-4.png\"></div>";
|
||||
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 (Object.prototype.hasOwnProperty.call(MarkerObject.PanicData, this.statusToDevice)) {
|
||||
var panicData = MarkerObject.PanicData[this.statusToDevice];
|
||||
if (panicData["ButtonPressed"].length > 0) {
|
||||
html += "<div class='alerts'><span class=\"bold\">Alerts:</span>";
|
||||
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;
|
||||
}
|
||||
},
|
||||
UpdateStatus: function () {
|
||||
for (var id in MarkerObject.LocationData) {
|
||||
if (Object.prototype.hasOwnProperty.call(MarkerObject.LocationData, id)) {
|
||||
@ -88,7 +119,7 @@
|
||||
}
|
||||
this._UpdateOverviewElement(positionItem, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/// private functions
|
||||
_UpdateOverviewElement: function (positionItem, id) {
|
||||
@ -159,37 +190,6 @@
|
||||
document.getElementById("pannels_admin").innerHTML = "<a href='/admin/' target='_blank'>Adminpannel</a>";
|
||||
}
|
||||
},
|
||||
_Update_pannels_info: function () {
|
||||
document.getElementById("pannels_info").innerHTML = "";
|
||||
if (Object.prototype.hasOwnProperty.call(MarkerObject.LocationData, this.statusToDevice)) {
|
||||
var positionItem = MarkerObject.LocationData[this.statusToDevice];
|
||||
var html = "<div class=\"name\">Name: <span class=\"bold\">" + positionItem["Name"] + "</span></div>";
|
||||
html += "<div class=\"batt\"><span class=\"bold\">Batterie:</span> " + positionItem["Battery"] + "V <img src=\"icons/akku/" + positionItem["Batterysimple"] + "-4.png\"></div>";
|
||||
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 (Object.prototype.hasOwnProperty.call(MarkerObject.PanicData, this.statusToDevice)) {
|
||||
var panicData = MarkerObject.PanicData[this.statusToDevice];
|
||||
if (panicData["ButtonPressed"].length > 0) {
|
||||
html += "<div class='alerts'><span class=\"bold\">Alerts:</span>";
|
||||
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 () {
|
||||
@ -207,7 +207,7 @@
|
||||
var html = "";
|
||||
for (var i = 0; i < json.length; i++) {
|
||||
var walert = json[i];
|
||||
html += "<div class='alertitem " + walert.Level +" "+ walert.Type + "'>" +
|
||||
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>" +
|
||||
|
Loading…
Reference in New Issue
Block a user