[1.3.0] New Gateway

## New Features
* Implement Lora-Gateway-Data 1.1.0 Format
## Bugfixes
## Changes
* Refactoring
* Make requests.conf not needed anymore.
This commit is contained in:
Philip Schell 2020-01-20 14:39:51 +01:00 committed by GitHub
commit 61ed34899d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 92 additions and 142 deletions

View File

@ -45,7 +45,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.create_deb.outputs.builddaterelease }}
release_name: Nightly from master
release_name: Nightly from ${{ steps.create_deb.outputs.builddaterelease }}
body: This is a nightly release. It may be not working properly.
draft: false
prerelease: true

View File

@ -1,5 +1,13 @@
# Changelogs
## 1.3.0 - New Gateway
### New Features
* Implement Lora-Gateway-Data 1.1.0 Format
### Bugfixes
### Changes
* Refactoring
* Make requests.conf not needed anymore.
## 1.2.10
### New Features
* Posibility to display sensor data on map

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
@ -10,32 +10,34 @@
<Description>Displays Items with Coordinates from Mqtt on a Map</Description>
<Company>Fraunhofer FIT</Company>
<PackageId>LoraMap.IoT.Fit.Fraunhofer</PackageId>
<Copyright>Copyright © Fraunhofer FIT, BlubbFish 2018 - 11.12.2019</Copyright>
<Copyright>Copyright © Fraunhofer FIT, BlubbFish 2018 - 20.01.2020</Copyright>
<Authors>BlubbFish</Authors>
<Version>1.2.10</Version>
<Version>1.3.0</Version>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageProjectUrl>https://github.com/MONICA-Project/lora-map</PackageProjectUrl>
<RepositoryUrl>https://github.com/MONICA-Project/lora-map.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<NeutralLanguage>de-DE</NeutralLanguage>
<PackageReleaseNotes>1.2.10 Refactoring is the thing
1.2.9 The PüMa Release
1.2.8 Improving the UI
1.2.7 Reorganise a lot of things, add Support for Cameradata
1.2.6 New Types of marker for person
1.2.5 Set textsize for every zoomlevel
1.2.4 Can draw Textmarkers on the Map, use MGRS (UTM) on the Map
1.2.3 #9 display polygons and marker on the map
1.2.2 Bugfix, if only recieve panic packet with gps data, update the marker on the map also
1.2.1 #6 Load the map from the Device
1.2.0 #4 Possible to Ex and Import Setting
1.1.7 #8 Editor for Names
1.1.6 #5 Create admin area
1.1.5 Add support for alert button
1.1.4 #3 Create icons for devices
1.1.3 #1 Click on icon and show details
1.1.2 #2 Show versions number in Site
1.1.1 Add Debian package config</PackageReleaseNotes>
<PackageReleaseNotes>
1.3.0 New Gateway
1.2.10 Refactoring is the thing
1.2.9 The PüMa Release
1.2.8 Improving the UI
1.2.7 Reorganise a lot of things, add Support for Cameradata
1.2.6 New Types of marker for person
1.2.5 Set textsize for every zoomlevel
1.2.4 Can draw Textmarkers on the Map, use MGRS (UTM) on the Map
1.2.3 #9 display polygons and marker on the map
1.2.2 Bugfix, if only recieve panic packet with gps data, update the marker on the map also
1.2.1 #6 Load the map from the Device
1.2.0 #4 Possible to Ex and Import Setting
1.1.7 #8 Editor for Names
1.1.6 #5 Create admin area
1.1.5 Add support for alert button
1.1.4 #3 Create icons for devices
1.1.3 #1 Click on icon and show details
1.1.2 #2 Show versions number in Site
1.1.1 Add Debian package config</PackageReleaseNotes>
<PackageTags>lora mqtt map lagekarte</PackageTags>
<StartupObject>Fraunhofer.Fit.IoT.LoraMap.Program</StartupObject>
</PropertyGroup>
@ -59,9 +61,6 @@
</ItemGroup>
<ItemGroup>
<None Update="config-example\requests.conf.example">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="config-example\settings.conf.example">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

View File

@ -44,7 +44,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin {
cont.Request.InputStream.Close();
reader.Close();
try {
JsonMapper.ToObject(rawData);
_ = JsonMapper.ToObject(rawData);
} catch (Exception) {
Helper.WriteError("501 - Error recieving " + filename + ", no valid json " + cont.Request.Url.PathAndQuery);
cont.Response.StatusCode = 501;
@ -74,7 +74,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin {
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;
Int64 sessionid;
while(true) {
sessionid = AdminSession.GetRandomSessionid();
if(!this.session.ContainsKey(sessionid)) {
@ -110,22 +110,24 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model.Admin {
private Boolean CheckAuth(HttpListenerContext cont) {
#if DEBUG
Helper.WriteError("200 - AUTH-Bypassed!");
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;
#else
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);
}
cont.Response.StatusCode = 403;
Helper.WriteError("403 - " + cont.Request.Url.PathAndQuery);
}
return false;
return false;
#endif
}
}
}

View File

@ -1,81 +1,32 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using LitJson;
namespace Fraunhofer.Fit.IoT.LoraMap.Model {
class AlarmItem {
public Double Rssi { get; private set; }
public Double Snr { get; private set; }
public DateTime Lorarecievedtime { get; private set; }
public DateTime Recievedtime { get; private set; }
public Double Latitude { get; private set; }
public Double Longitude { get; private set; }
public UTMData UTM { get; private set; }
public Double Hdop { get; private set; }
public Boolean Fix { get; private set; }
public Double Height { get; private set; }
public List<DateTime> ButtonPressed => this.buttonhistory.Keys.ToList();
public class AlarmItem : PositionItem {
private readonly SortedDictionary<DateTime, String> buttonhistory = new SortedDictionary<DateTime, String>();
public AlarmItem(JsonData json) => this.Update(json);
public List<DateTime> ButtonPressed => this.buttonhistory.Keys.ToList();
public void Update(JsonData json) {
this.Rssi = json["Rssi"].IsInt ? (Int32)json["Rssi"] : (Double)json["Rssi"];
this.Snr = json["Snr"].IsInt ? (Int32)json["Snr"] : (Double)json["Snr"];
if (DateTime.TryParse((String)json["Receivedtime"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) {
this.Lorarecievedtime = updatetime.ToUniversalTime();
}
this.Recievedtime = DateTime.UtcNow;
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"];
if (!this.Fix) {
this.Latitude = json["Gps"]["LastLatitude"].IsInt ? (Int32)json["Gps"]["LastLatitude"] : (Double)json["Gps"]["LastLatitude"];
this.Longitude = json["Gps"]["LastLongitude"].IsInt ? (Int32)json["Gps"]["LastLongitude"] : (Double)json["Gps"]["LastLongitude"];
}
this.UTM = new UTMData(this.Latitude, this.Longitude);
this.Hdop = json["Gps"]["Hdop"].IsInt ? (Int32)json["Gps"]["Hdop"] : (Double)json["Gps"]["Hdop"];
this.Height = json["Gps"]["Height"].IsInt ? (Int32)json["Gps"]["Height"] : (Double)json["Gps"]["Height"];
public AlarmItem(JsonData json) : base(json, null) {
}
public override void Update(JsonData json) {
base.Update(json);
this.SetHistory(json);
}
private void SetHistory(JsonData json) {
String key = json["BatteryLevel"].ToString();
key += "_" + json["Calculatedcrc"].ToString();
key += "_" + json["Gps"]["Hdop"].ToString();
key += "_" + json["Gps"]["Height"].ToString();
key += "_" + json["Gps"]["Fix"].ToString();
key += "_" + json["Gps"]["LastLatitude"].ToString();
key += "_" + json["Gps"]["LastLongitude"].ToString();
key += "_" + json["Gps"]["Time"].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());
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());
}
}
}
}
}
public static String GetId(JsonData json) => (String)json["Name"];
public static Boolean CheckJson(JsonData json) =>
json.ContainsKey("Rssi") && (json["Rssi"].IsDouble || json["Rssi"].IsInt)
&& json.ContainsKey("Snr") && (json["Snr"].IsDouble || json["Snr"].IsInt)
&& json.ContainsKey("Receivedtime") && json["Receivedtime"].IsString
&& 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("LastLatitude") && (json["Gps"]["LastLatitude"].IsDouble || json["Gps"]["LastLatitude"].IsInt)
&& json["Gps"].ContainsKey("LastLongitude") && (json["Gps"]["LastLongitude"].IsDouble || json["Gps"]["LastLongitude"].IsInt)
&& json["Gps"].ContainsKey("LastGPSPos") && json["Gps"]["LastGPSPos"].IsString
&& json["Gps"].ContainsKey("Hdop") && (json["Gps"]["Hdop"].IsDouble || json["Gps"]["Hdop"].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 &&
json.ContainsKey("Calculatedcrc") && json["Calculatedcrc"].IsInt;
}
}
}

View File

@ -3,7 +3,10 @@ using System.Globalization;
using LitJson;
namespace Fraunhofer.Fit.IoT.LoraMap.Model {
class PositionItem {
public class PositionItem {
private Double _lastLat = 0;
private Double _lastLon = 0;
public Double Rssi { get; private set; }
public Double Snr { get; private set; }
public DateTime Lorarecievedtime { get; private set; }
@ -27,7 +30,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model {
}
public void UpdateMarker(JsonData marker, String id) {
if(marker.ContainsKey(id)) {
if(marker != null && marker.ContainsKey(id)) {
this.Name = marker[id].ContainsKey("name") && marker[id]["name"].IsString ? (String)marker[id]["name"] : id;
this.Icon = marker[id].ContainsKey("marker.svg") && marker[id]["marker.svg"].IsObject ? Marker.ParseMarkerConfig(marker[id]["marker.svg"], this.Name) : marker[id].ContainsKey("icon") && marker[id]["icon"].IsString ? (String)marker[id]["icon"] : null;
this.Group = marker[id].ContainsKey("Group") && marker[id]["Group"].IsString ? (String)marker[id]["Group"] : "no";
@ -38,45 +41,39 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model {
}
}
public static Boolean CheckJson(JsonData json) =>
json.ContainsKey("Rssi") && (json["Rssi"].IsDouble || json["Rssi"].IsInt)
&& json.ContainsKey("Snr") && (json["Snr"].IsDouble || json["Snr"].IsInt)
&& json.ContainsKey("Receivedtime") && json["Receivedtime"].IsString
&& json.ContainsKey("BatteryLevel") && (json["BatteryLevel"].IsDouble || json["BatteryLevel"].IsInt)
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("LastLatitude") && (json["Gps"]["LastLatitude"].IsDouble || json["Gps"]["LastLatitude"].IsInt)
&& json["Gps"].ContainsKey("LastLongitude") && (json["Gps"]["LastLongitude"].IsDouble || json["Gps"]["LastLongitude"].IsInt)
&& json["Gps"].ContainsKey("LastGPSPos") && json["Gps"]["LastGPSPos"].IsString
&& json["Gps"].ContainsKey("Hdop") && (json["Gps"]["Hdop"].IsDouble || json["Gps"]["Hdop"].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 void Update(JsonData json) {
this.Rssi = json["Rssi"].IsInt ? (Int32)json["Rssi"] : (Double)json["Rssi"];
this.Snr = json["Snr"].IsInt ? (Int32)json["Snr"] : (Double)json["Snr"];
if(DateTime.TryParse((String)json["Receivedtime"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) {
this.Lorarecievedtime = updatetime.ToUniversalTime();
}
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;
this.Recievedtime = DateTime.UtcNow;
this.Battery = Math.Round(json["BatteryLevel"].IsInt ? (Int32)json["BatteryLevel"] : (Double)json["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"];
if(!this.Fix) {
this.Latitude = json["Gps"]["LastLatitude"].IsInt ? (Int32)json["Gps"]["LastLatitude"] : (Double)json["Gps"]["LastLatitude"];
this.Longitude = json["Gps"]["LastLongitude"].IsInt ? (Int32)json["Gps"]["LastLongitude"] : (Double)json["Gps"]["LastLongitude"];
}
this.UTM = new UTMData(this.Latitude, this.Longitude);
if(DateTime.TryParse((String)json["Gps"]["LastGPSPos"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime lastgpstime)) {
this.Lastgpspostime = lastgpstime.ToUniversalTime();
}
this.Hdop = json["Gps"]["Hdop"].IsInt ? (Int32)json["Gps"]["Hdop"] : (Double)json["Gps"]["Hdop"];
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;
if(!this.Fix) {
this.Latitude = this._lastLat;
this.Longitude = this._lastLon;
} else {
this._lastLat = this.Latitude;
this._lastLon = this.Longitude;
this.Lastgpspostime = DateTime.UtcNow;
}
this.UTM = new UTMData(this.Latitude, this.Longitude);
}

View File

@ -12,16 +12,11 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
_ = Console.ReadLine();
return;
}
if(!InIReader.ConfigExist("requests")) {
Helper.WriteError("requests.ini not found!");
_ = Console.ReadLine();
return;
}
InIReader ini = InIReader.GetInstance("settings");
Dictionary<String, String> backenddata = ini.GetSection("mqtt");
backenddata.Add("topic", "lora/#;camera/#;sfn/#");
ADataBackend b = (ADataBackend)ABackend.GetInstance(backenddata, ABackend.BackendType.Data);
_ = new Server(b, ini.GetSection("webserver"), InIReader.GetInstance("requests"));
_ = new Server(b, ini.GetSection("webserver"));
}
}
}

View File

@ -31,7 +31,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
private readonly Object lockDensy = new Object();
private readonly Object lockSensor = new Object();
public Server(ADataBackend backend, Dictionary<String, String> settings, InIReader requests) : base(backend, settings, requests) {
public Server(ADataBackend backend, Dictionary<String, String> settings) : base(backend, settings, null) {
this.logger.SetPath(settings["loggingpath"]);
this.CheckJsonFiles();
this.admin = new AdminModel(settings);
@ -71,7 +71,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
protected override void Backend_MessageIncomming(Object sender, BackendEvent mqtt) {
try {
JsonData d = JsonMapper.ToObject(mqtt.Message);
if(PositionItem.CheckJson(d) && ((String)mqtt.From).Contains("lora/data")) {
if(((String)mqtt.From).Contains("lora/data") && PositionItem.CheckJson(d)) {
String name = PositionItem.GetId(d);
lock(this.lockData) {
if(this.positions.ContainsKey(name)) {
@ -81,8 +81,8 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
}
}
Console.WriteLine("Koordinate erhalten!");
} else if(AlarmItem.CheckJson(d) && ((String)mqtt.From).Contains("lora/panic")) {
String name = AlarmItem.GetId(d);
} else if(((String)mqtt.From).Contains("lora/panic") && PositionItem.CheckJson(d)) {
String name = PositionItem.GetId(d);
lock(this.lockPanic) {
if(this.alarms.ContainsKey(name)) {
this.alarms[name].Update(d);
@ -98,7 +98,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap {
}
}
Console.WriteLine("PANIC erhalten!");
} else if(Camera.CheckJson(d) && ((String)mqtt.From).Contains("camera/count")) {
} else if(((String)mqtt.From).Contains("camera/count") && Camera.CheckJson(d)) {
String cameraid = Camera.GetId(d);
lock(this.lockCount) {
if(this.counter.ContainsKey(cameraid)) {

View File

@ -1,2 +0,0 @@
[js/map.js]
start_location=50.7, 7.2