diff --git a/Lora-Map/Lora-Map.csproj b/Lora-Map/Lora-Map.csproj index a34852e..1858338 100644 --- a/Lora-Map/Lora-Map.csproj +++ b/Lora-Map/Lora-Map.csproj @@ -46,9 +46,9 @@ - + - + @@ -115,6 +115,9 @@ PreserveNewest + + PreserveNewest + @@ -134,7 +137,7 @@ PreserveNewest - + PreserveNewest diff --git a/Lora-Map/Model/Panicclient.cs b/Lora-Map/Model/AlarmItem.cs similarity index 85% rename from Lora-Map/Model/Panicclient.cs rename to Lora-Map/Model/AlarmItem.cs index 344e64c..7f81e30 100644 --- a/Lora-Map/Model/Panicclient.cs +++ b/Lora-Map/Model/AlarmItem.cs @@ -3,26 +3,26 @@ using System.Globalization; using LitJson; namespace Fraunhofer.Fit.IoT.LoraMap.Model { - class Panicclient { + class AlarmItem { public Double Rssi { get; private set; } public Double Snr { get; private set; } - public DateTime Upatedtime { 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 Double Hdop { get; private set; } public Boolean Fix { get; private set; } public Double Height { get; private set; } - public DateTime Triggerdtime { get; private set; } - public Panicclient(JsonData json) => this.Update(json); + public AlarmItem(JsonData json) => this.Update(json); public void Update(JsonData json) { - this.Triggerdtime = DateTime.Now; this.Rssi = (Double)json["Rssi"]; this.Snr = (Double)json["Snr"]; if(DateTime.TryParse((String)json["Receivedtime"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) { - this.Upatedtime = updatetime; + this.Lorarecievedtime = updatetime.ToUniversalTime(); } + this.Recievedtime = DateTime.UtcNow; this.Latitude = (Double)json["Gps"]["Latitude"]; this.Longitude = (Double)json["Gps"]["Longitude"]; this.Fix = (Boolean)json["Gps"]["Fix"]; diff --git a/Lora-Map/Model/Botclient.cs b/Lora-Map/Model/PositionItem.cs similarity index 82% rename from Lora-Map/Model/Botclient.cs rename to Lora-Map/Model/PositionItem.cs index 5ea3609..6044e56 100644 --- a/Lora-Map/Model/Botclient.cs +++ b/Lora-Map/Model/PositionItem.cs @@ -3,13 +3,15 @@ using System.Globalization; using LitJson; namespace Fraunhofer.Fit.IoT.LoraMap.Model { - class Botclient { + class PositionItem { public Double Rssi { get; private set; } public Double Snr { get; private set; } - public DateTime Upatedtime { 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 Double Hdop { get; private set; } + public DateTime Lastgpspostime { get; private set; } public Double Battery { get; private set; } public Int32 Batterysimple { get; private set; } public Boolean Fix { get; private set; } @@ -17,7 +19,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { public String Name { get; private set; } public String Icon { get; private set; } - public Botclient(JsonData json, JsonData marker) { + public PositionItem(JsonData json, JsonData marker) { this.Update(json); String id = GetId(json); if(marker.ContainsKey(id)) { @@ -48,6 +50,7 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { && json["Gps"].ContainsKey("Longitude") && json["Gps"]["Longitude"].IsDouble && json["Gps"].ContainsKey("LastLatitude") && json["Gps"]["LastLatitude"].IsDouble && json["Gps"].ContainsKey("LastLongitude") && json["Gps"]["LastLongitude"].IsDouble + && json["Gps"].ContainsKey("LastLongitude") && json["Gps"]["LastGPSPos"].IsString && json["Gps"].ContainsKey("Hdop") && json["Gps"]["Hdop"].IsDouble && json["Gps"].ContainsKey("Fix") && json["Gps"]["Fix"].IsBoolean && json["Gps"].ContainsKey("Height") && json["Gps"]["Height"].IsDouble @@ -58,8 +61,9 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { this.Rssi = (Double)json["Rssi"]; this.Snr = (Double)json["Snr"]; if(DateTime.TryParse((String)json["Receivedtime"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime updatetime)) { - this.Upatedtime = updatetime; + this.Lorarecievedtime = updatetime.ToUniversalTime(); } + this.Recievedtime = DateTime.UtcNow; this.Battery = Math.Round((Double)json["BatteryLevel"], 2); if(this.Battery < 3) { this.Batterysimple = 0; @@ -79,6 +83,9 @@ namespace Fraunhofer.Fit.IoT.LoraMap.Model { this.Latitude = (Double)json["Gps"]["LastLatitude"]; this.Longitude = (Double)json["Gps"]["LastLongitude"]; } + if(DateTime.TryParse((String)json["Gps"]["LastGPSPos"], DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeUniversal, out DateTime lastgpstime)) { + this.Lastgpspostime = lastgpstime.ToUniversalTime(); + } this.Hdop = (Double)json["Gps"]["Hdop"]; this.Height = (Double)json["Gps"]["Height"]; } diff --git a/Lora-Map/Properties/AssemblyInfo.cs b/Lora-Map/Properties/AssemblyInfo.cs index 2dc5b64..b05a0f2 100644 --- a/Lora-Map/Properties/AssemblyInfo.cs +++ b/Lora-Map/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Fraunhofer FIT")] [assembly: AssemblyProduct("Lora-Map")] -[assembly: AssemblyCopyright("Copyright © 2018 - 10.03.2019")] +[assembly: AssemblyCopyright("Copyright © 2018 - 30.03.2019")] [assembly: AssemblyTrademark("Fraunhofer FIT, BlubbFish")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("de-DE")] @@ -33,12 +33,13 @@ using System.Runtime.InteropServices; // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.1.4")] -[assembly: AssemblyFileVersion("1.1.4")] +[assembly: AssemblyVersion("1.1.5")] +[assembly: AssemblyFileVersion("1.1.5")] /* * 1.1.1 Add Debian package config * 1.1.2 #2 Show versions number in Site * 1.1.3 #1 Click on icon and show details * 1.1.4 #3 Create icons for devices +* 1.1.5 Add support for alert button */ diff --git a/Lora-Map/Server.cs b/Lora-Map/Server.cs index bfda7b3..b958344 100644 --- a/Lora-Map/Server.cs +++ b/Lora-Map/Server.cs @@ -13,8 +13,8 @@ using LitJson; namespace Fraunhofer.Fit.IoT.LoraMap { class Server : Webserver { - private readonly SortedDictionary locations = new SortedDictionary(); - private readonly SortedDictionary panics = new SortedDictionary(); + private readonly SortedDictionary positions = new SortedDictionary(); + private readonly SortedDictionary alarms = new SortedDictionary(); private readonly JsonData marker; private readonly Dictionary markertable = new Dictionary(); @@ -23,20 +23,20 @@ namespace Fraunhofer.Fit.IoT.LoraMap { protected override void Backend_MessageIncomming(Object sender, BackendEvent e) { try { JsonData d = JsonMapper.ToObject(e.Message); - if (Botclient.CheckJson(d) && ((String)e.From).Contains("lora/data")) { - String name = Botclient.GetId(d); - if (this.locations.ContainsKey(name)) { - this.locations[name].Update(d); + if (PositionItem.CheckJson(d) && ((String)e.From).Contains("lora/data")) { + String name = PositionItem.GetId(d); + if (this.positions.ContainsKey(name)) { + this.positions[name].Update(d); } else { - this.locations.Add(name, new Botclient(d, this.marker)); + this.positions.Add(name, new PositionItem(d, this.marker)); } Console.WriteLine("Koordinate erhalten!"); - } else if(Panicclient.CheckJson(d) && ((String)e.From).Contains("lora/panic")) { - String name = Panicclient.GetId(d); - if(this.panics.ContainsKey(name)) { - this.panics[name].Update(d); + } else if(AlarmItem.CheckJson(d) && ((String)e.From).Contains("lora/panic")) { + String name = AlarmItem.GetId(d); + if(this.alarms.ContainsKey(name)) { + this.alarms[name].Update(d); } else { - this.panics.Add(name, new Panicclient(d)); + this.alarms.Add(name, new AlarmItem(d)); } Console.WriteLine("PANIC erhalten!"); } @@ -48,10 +48,10 @@ namespace Fraunhofer.Fit.IoT.LoraMap { protected override void SendResponse(HttpListenerContext cont) { try { if (cont.Request.Url.PathAndQuery.StartsWith("/loc")) { - this.SendJsonResponse(this.locations, cont); + this.SendJsonResponse(this.positions, cont); return; } else if(cont.Request.Url.PathAndQuery.StartsWith("/panic")) { - this.SendJsonResponse(this.panics, cont); + this.SendJsonResponse(this.alarms, cont); return; } else if (cont.Request.Url.PathAndQuery.StartsWith("/icons/marker/Marker.svg") && cont.Request.Url.PathAndQuery.Contains("?")) { String hash = cont.Request.Url.PathAndQuery.Substring(cont.Request.Url.PathAndQuery.IndexOf('?') + 1); @@ -64,6 +64,9 @@ namespace Fraunhofer.Fit.IoT.LoraMap { cont.Response.OutputStream.Write(buf, 0, buf.Length); Console.WriteLine("200 - " + cont.Request.Url.PathAndQuery); return; + } else if(cont.Request.Url.PathAndQuery.StartsWith("/currenttime")) { + this.SendJsonResponse(new Dictionary() { { "utc", DateTime.UtcNow } }, cont); + return; } } catch (Exception e) { Helper.WriteError("500 - " + e.Message); diff --git a/Lora-Map/config-example/requests.conf.example b/Lora-Map/config-example/requests.conf.example index 1d31b5d..5d9d8f8 100644 --- a/Lora-Map/config-example/requests.conf.example +++ b/Lora-Map/config-example/requests.conf.example @@ -1,2 +1,2 @@ -[js/nav.js] +[js/map.js] start_location=50.7, 7.2 \ No newline at end of file diff --git a/Lora-Map/resources/index.html b/Lora-Map/resources/index.html index 034f227..ed89f22 100644 --- a/Lora-Map/resources/index.html +++ b/Lora-Map/resources/index.html @@ -35,7 +35,8 @@ - + + diff --git a/Lora-Map/resources/js/functions.js b/Lora-Map/resources/js/functions.js new file mode 100644 index 0000000..31961fa --- /dev/null +++ b/Lora-Map/resources/js/functions.js @@ -0,0 +1,43 @@ +setInterval(timecorrectionrunner, 60000); +timecorrectionrunner(); + +function timecorrectionrunner() { + var timecorrection = new XMLHttpRequest(); + timecorrection.onreadystatechange = parseAjaxTimecorrection; + timecorrection.open("GET", "http://{%REQUEST_URL_HOST%}:8080/currenttime", true); + timecorrection.send(); +} + +var timeOffset = 0; + +function parseAjaxTimecorrection() { + if (this.readyState === 4 && this.status === 200) { + utcobject = JSON.parse(this.responseText); + if (utcobject.hasOwnProperty("utc")) { + timeOffset = Date.now() - Date.parse(utcobject["utc"]); + } + } +} + +function timeCalculation(timestr, type) { + if (type === "diffraw" || type === "difftext") { + var diff = Math.round((Date.now() - Date.parse(timestr) - timeOffset) / 1000); + if (type === "diffraw") { + return diff; + } + if (diff < 60) { + return diff + " s"; + } + if (diff < 60 * 60) { + return Math.floor(diff / 60) + " m"; + } + if (diff < 60 * 60 * 24) { + return Math.floor(diff / (60 * 60)) + " h"; + } + return Math.floor(diff / (60 * 60 * 24)) + " d"; + } else if (type === "str") { + var date = new Date(Date.parse(timestr) + timeOffset); + var str = date.toLocaleString(); + return str; + } +} \ No newline at end of file diff --git a/Lora-Map/resources/js/nav.js b/Lora-Map/resources/js/map.js similarity index 100% rename from Lora-Map/resources/js/nav.js rename to Lora-Map/resources/js/map.js diff --git a/Lora-Map/resources/js/marker.js b/Lora-Map/resources/js/marker.js index 6d54fb7..28a9fd8 100644 --- a/Lora-Map/resources/js/marker.js +++ b/Lora-Map/resources/js/marker.js @@ -19,24 +19,24 @@ function parseAjaxLoc() { serverLocation = JSON.parse(this.responseText); for (var key in serverLocation) { if (serverLocation.hasOwnProperty(key)) { - var markeritem = serverLocation[key]; - if (markeritem['Latitude'] !== 0 || markeritem['Longitude'] !== 0) { + var positionItem = serverLocation[key]; + if (positionItem['Latitude'] !== 0 || positionItem['Longitude'] !== 0) { if (!markers.hasOwnProperty(key)) { var marker = null; - if (markeritem['Icon'] === null) { - marker = L.marker([markeritem['Latitude'], markeritem['Longitude']], { 'title': markeritem['Name'] }); + if (positionItem['Icon'] === null) { + marker = L.marker([positionItem['Latitude'], positionItem['Longitude']], { 'title': positionItem['Name'] }); } else { var myIcon = L.divIcon({ className: 'pos-marker', iconSize: [56, 80], iconAnchor: [0, 80], - html: '' + html: '' }); - marker = L.marker([markeritem['Latitude'], markeritem['Longitude']], { 'title': markeritem['Name'], 'icon': myIcon }); + marker = L.marker([positionItem['Latitude'], positionItem['Longitude']], { 'title': positionItem['Name'], 'icon': myIcon }); } markers[key] = marker.addTo(mymap).on("click", showMarkerInfo, key); } else { - markers[key].setLatLng([markeritem['Latitude'], markeritem['Longitude']]); + markers[key].setLatLng([positionItem['Latitude'], positionItem['Longitude']]); } } } @@ -51,13 +51,13 @@ function parseAjaxPanic() { var panics = JSON.parse(this.responseText); for (var id in panics) { if (panics.hasOwnProperty(id)) { - var panicitem = panics[id]; + var alertItem = panics[id]; if (markers.hasOwnProperty(id)) { var marker = markers[id]; - if (timeDiffRaw(panicitem["Triggerdtime"]) <= 10 && marker._icon.className.indexOf(" marker-alert") === -1) { + if (timeCalculation(alertItem["Recievedtime"], "diffraw") <= 10 && marker._icon.className.indexOf(" marker-alert") === -1) { marker._icon.className += " marker-alert"; showMarkerInfoPerId(id); - } else if (timeDiffRaw(panicitem["Triggerdtime"]) > 10 && marker._icon.className.indexOf(" marker-alert") !== -1) { + } else if (timeCalculation(alertItem["Recievedtime"], "diffraw") > 10 && marker._icon.className.indexOf(" marker-alert") !== -1) { marker._icon.className = marker._icon.className.replace(" marker-alert", ""); } } diff --git a/Lora-Map/resources/js/menu.js b/Lora-Map/resources/js/menu.js index 442d619..e94b341 100644 --- a/Lora-Map/resources/js/menu.js +++ b/Lora-Map/resources/js/menu.js @@ -39,19 +39,20 @@ function showMarkerInfoMenu() { function updateDeviceStatus() { document.getElementById("pannels_info").innerHTML = ""; if (serverLocation.hasOwnProperty(statusToDevice)) { - var markeritem = serverLocation[statusToDevice]; - var html = "
Name: " + markeritem["Name"] + "
"; - html += "
Batterie: " + markeritem["Battery"] + "V
"; - if (markeritem["Fix"]) { + var positionItem = serverLocation[statusToDevice]; + var html = "
Name: " + positionItem["Name"] + "
"; + html += "
Batterie: " + positionItem["Battery"] + "V
"; + if (positionItem["Fix"]) { html += "
GPS-Empfang
"; } else { html += "
kein GPS-Empfang
"; } - html += "
" + markeritem["Latitude"].toFixed(7) + ", " + markeritem["Longitude"].toFixed(7) + "
"; - html += "
Höhe: " + markeritem["Height"].toFixed(1) + " m
"; - html += "
HDOP: " + markeritem["Hdop"].toFixed(1) + "
"; - html += "
Update: " + markeritem["Upatedtime"] + "
Vor: " + timeDiffToText(markeritem["Upatedtime"]) + "
"; - html += "
RSSI: " + markeritem["Rssi"] + ", SNR: " + markeritem["Snr"] + "
"; + html += "
" + positionItem["Latitude"].toFixed(7) + ", " + positionItem["Longitude"].toFixed(7) + "
"; + html += "
Letzter Wert: Vor: " + timeCalculation(positionItem["Lastgpspostime"], "difftext") + "
"; + html += "
Höhe: " + positionItem["Height"].toFixed(1) + " m
"; + html += "
HDOP: " + positionItem["Hdop"].toFixed(1) + "
"; + html += "
Update: " + timeCalculation(positionItem["Recievedtime"], "str") + "
Vor: " + timeCalculation(positionItem["Recievedtime"], "difftext") + "
"; + html += "
RSSI: " + positionItem["Rssi"] + ", SNR: " + positionItem["Snr"] + "
"; document.getElementById("pannels_info").innerHTML = html; } } @@ -61,71 +62,52 @@ var overviewStatus = new Array(); function updateStatus() { for (var id in serverLocation) { if (serverLocation.hasOwnProperty(id)) { - var markeritem = serverLocation[id]; + var positionItem = serverLocation[id]; if (typeof overviewStatus[id] === "undefined") { - overviewStatus[id] = createOverviewElement(markeritem, id); + overviewStatus[id] = createOverviewElement(positionItem, id); document.getElementById("pannels_pos").appendChild(overviewStatus[id]); } - updateOverviewElement(markeritem, id); + updateOverviewElement(positionItem, id); } } } -function updateOverviewElement(markeritem, id) { - if (markeritem["Batterysimple"] === 0) { +function updateOverviewElement(positionItem, id) { + if (positionItem["Batterysimple"] === 0) { document.getElementById("overview-color-id-" + id).style.backgroundColor = "red"; - } else if (markeritem["Batterysimple"] === 1 || markeritem["Batterysimple"] === 2) { + } else if (positionItem["Batterysimple"] === 1 || positionItem["Batterysimple"] === 2) { document.getElementById("overview-color-id-" + id).style.backgroundColor = "yellow"; - } else if (markeritem["Batterysimple"] === 3 || markeritem["Batterysimple"] === 4) { + } else if (positionItem["Batterysimple"] === 3 || positionItem["Batterysimple"] === 4) { document.getElementById("overview-color-id-" + id).style.backgroundColor = "green"; } - document.getElementById("overview-name-id-" + id).innerText = markeritem["Name"]; - document.getElementById("overview-akkuimg-id-" + id).src = "icons/akku/" + markeritem["Batterysimple"] + "-4.png"; - if (markeritem["Fix"]) { + document.getElementById("overview-name-id-" + id).innerText = positionItem["Name"]; + document.getElementById("overview-akkuimg-id-" + id).src = "icons/akku/" + positionItem["Batterysimple"] + "-4.png"; + if (positionItem["Fix"]) { document.getElementById("overview-gps-id-" + id).innerText = "GPS-Empfang"; document.getElementById("overview-gps-id-" + id).style.color = "green"; } else { document.getElementById("overview-gps-id-" + id).innerText = "kein GPS-Empfang"; document.getElementById("overview-gps-id-" + id).style.color = "red"; } - document.getElementById("overview-update-id-" + id).innerText = "Letzter Datenempfang: vor " + timeDiffToText(markeritem["Upatedtime"]); + document.getElementById("overview-update-id-" + id).innerText = "Letzter Datenempfang: vor " + timeCalculation(positionItem["Recievedtime"], "difftext"); } -function createOverviewElement(markeritem, id) { +function createOverviewElement(positionItem, id) { var divItem = document.createElement("div"); divItem.className = "item"; divItem.onclick = showMarkerInfoMenu; divItem.setAttribute("rel", id); divItem.innerHTML = ""; - if (markeritem['Icon'] !== null) { - divItem.innerHTML += ""; + if (positionItem['Icon'] !== null) { + divItem.innerHTML += ""; } else { divItem.innerHTML += ""; } divItem.innerHTML += "
" + "" + - "" + + "" + "
"; divItem.innerHTML += "
kein GPS-Empfang
"; - divItem.innerHTML += "
Letzter Datenempfang: vor " + timeDiffToText(markeritem["Upatedtime"]) + "
"; + divItem.innerHTML += "
Letzter Datenempfang: vor " + timeCalculation(positionItem["Recievedtime"], "difftext") + "
"; return divItem; -} - -function timeDiffToText(time) { - var diff = Date.now() - Date.parse(time); - diff = Math.round(diff / 1000); - if (diff < 60) { - return diff + " s"; - } - if (diff < 60 * 60) { - return Math.floor(diff / 60) + " m"; - } - if (diff < 60 * 60 * 24) { - return Math.floor(diff / (60 * 60)) + " h"; - } - return Math.floor(diff / (60 * 60 * 24)) + " d"; -} - -function timeDiffRaw(time) { - return (Date.now() - Date.parse(time)) / 1000; } \ No newline at end of file