From 617fbc4dea26c86ee615c9035a70784d8bf98ae2 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Sun, 21 Apr 2019 15:29:00 +0200 Subject: [PATCH] [1.2.1] #6 Load the map from the Device --- Lora-Map/Lora-Map.csproj | 8 +++- Lora-Map/Properties/AssemblyInfo.cs | 7 +-- Lora-Map/Server.cs | 56 ++++++++++++++++++---- Lora-Map/resources/css/icons/failtile.png | Bin 0 -> 4011 bytes Lora-Map/resources/js/map.js | 51 ++++++++++++++++++-- 5 files changed, 105 insertions(+), 17 deletions(-) create mode 100644 Lora-Map/resources/css/icons/failtile.png diff --git a/Lora-Map/Lora-Map.csproj b/Lora-Map/Lora-Map.csproj index f368f5e..00417d5 100644 --- a/Lora-Map/Lora-Map.csproj +++ b/Lora-Map/Lora-Map.csproj @@ -68,7 +68,6 @@ - PreserveNewest @@ -89,6 +88,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -138,7 +140,9 @@ PreserveNewest - + + PreserveNewest + PreserveNewest diff --git a/Lora-Map/Properties/AssemblyInfo.cs b/Lora-Map/Properties/AssemblyInfo.cs index e4a70a7..36c65b8 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 - 15.04.2019")] +[assembly: AssemblyCopyright("Copyright © 2018 - 21.04.2019")] [assembly: AssemblyTrademark("Fraunhofer FIT, BlubbFish")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("de-DE")] @@ -33,8 +33,8 @@ using System.Runtime.InteropServices; // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.0")] -[assembly: AssemblyFileVersion("1.2.0")] +[assembly: AssemblyVersion("1.2.1")] +[assembly: AssemblyFileVersion("1.2.1")] /* * 1.1.1 Add Debian package config @@ -45,4 +45,5 @@ using System.Runtime.InteropServices; * 1.1.6 #5 Create admin area * 1.1.7 #8 Editor for Names * 1.2.0 #4 Possible to Ex and Import Setting +* 1.2.1 #6 Load the map from the Device */ diff --git a/Lora-Map/Server.cs b/Lora-Map/Server.cs index 118d323..f41be46 100644 --- a/Lora-Map/Server.cs +++ b/Lora-Map/Server.cs @@ -12,8 +12,7 @@ using Fraunhofer.Fit.IoT.LoraMap.Model.Admin; using LitJson; namespace Fraunhofer.Fit.IoT.LoraMap { - class Server : Webserver - { + class Server : Webserver { private readonly SortedDictionary positions = new SortedDictionary(); private readonly SortedDictionary alarms = new SortedDictionary(); private JsonData marker; @@ -49,9 +48,9 @@ namespace Fraunhofer.Fit.IoT.LoraMap { protected override void Backend_MessageIncomming(Object sender, BackendEvent e) { try { JsonData d = JsonMapper.ToObject(e.Message); - if (PositionItem.CheckJson(d) && ((String)e.From).Contains("lora/data")) { + if(PositionItem.CheckJson(d) && ((String)e.From).Contains("lora/data")) { String name = PositionItem.GetId(d); - if (this.positions.ContainsKey(name)) { + if(this.positions.ContainsKey(name)) { this.positions[name].Update(d); } else { this.positions.Add(name, new PositionItem(d, this.marker)); @@ -66,20 +65,20 @@ namespace Fraunhofer.Fit.IoT.LoraMap { } Console.WriteLine("PANIC erhalten!"); } - } catch (Exception ex) { + } catch(Exception ex) { Helper.WriteError(ex.Message); } } protected override Boolean SendWebserverResponse(HttpListenerContext cont) { try { - if (cont.Request.Url.PathAndQuery.StartsWith("/loc")) { + if(cont.Request.Url.PathAndQuery.StartsWith("/loc")) { return SendJsonResponse(this.positions, cont); } else if(cont.Request.Url.PathAndQuery.StartsWith("/panic")) { return SendJsonResponse(this.alarms, cont); - } else if (cont.Request.Url.PathAndQuery.StartsWith("/icons/marker/Marker.svg") && cont.Request.Url.PathAndQuery.Contains("?")) { + } else if(cont.Request.Url.PathAndQuery.StartsWith("/icons/marker/Marker.svg") && cont.Request.Url.PathAndQuery.Contains("?")) { String hash = cont.Request.Url.PathAndQuery.Substring(cont.Request.Url.PathAndQuery.IndexOf('?') + 1); - if (!this.markertable.ContainsKey(hash)) { + if(!this.markertable.ContainsKey(hash)) { this.markertable.Add(hash, new Marker(hash)); } cont.Response.ContentType = "image/svg+xml"; @@ -92,13 +91,52 @@ namespace Fraunhofer.Fit.IoT.LoraMap { return SendJsonResponse(new Dictionary() { { "utc", DateTime.UtcNow } }, cont); } else if(cont.Request.Url.PathAndQuery.StartsWith("/admin")) { return this.admin.ParseReuqest(cont); + } else if(cont.Request.Url.PathAndQuery.StartsWith("/getlayer")) { + return SendJsonResponse(this.FindMapLayer(cont.Request), cont); + } else if(cont.Request.Url.PathAndQuery.StartsWith("/maps/")) { + return SendFileResponse(cont, "resources", false); } - } catch (Exception e) { + } catch(Exception e) { Helper.WriteError("500 - " + e.Message); cont.Response.StatusCode = 500; return false; } return SendFileResponse(cont); } + + private Dictionary> FindMapLayer(HttpListenerRequest request) { + Dictionary> ret = new Dictionary> { + { "online", new Dictionary() { + { "title", "Online Map" }, + { "url", "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" }, + { "attribution", "© OpenStreetMap contributors" }, + { "minZoom", 1 }, + { "maxZoom", 18 } + } } + }; + if(Directory.Exists("resources" + Path.DirectorySeparatorChar + "maps")) { + String[] dirs = Directory.GetDirectories("resources" + Path.DirectorySeparatorChar + "maps"); + foreach(String dir in dirs) { + if(File.Exists(dir + Path.DirectorySeparatorChar + "tiles.json")) { + try { + JsonData map = JsonMapper.ToObject(File.ReadAllText(dir + Path.DirectorySeparatorChar + "tiles.json")); + Dictionary entry = new Dictionary { + { "title", (String)map["name"] }, + { "url", (String)map["tiles"][0] }, + { "attribution", (String)map["attribution"] }, + { "minZoom", (Int32)map["minzoom"] }, + { "maxZoom", (Int32)map["maxzoom"] }, + { "bounds", new Dictionary() { + { "corner1", new Double[] { (Double)map["bounds"][0], (Double)map["bounds"][1] } }, + { "corner2", new Double[] { (Double)map["bounds"][2], (Double)map["bounds"][3] } } + } } + }; + ret.Add(dir.Substring(("resources" + Path.DirectorySeparatorChar + "maps").Length+1), entry); + } catch { } + } + } + } + return ret; + } } } \ No newline at end of file diff --git a/Lora-Map/resources/css/icons/failtile.png b/Lora-Map/resources/css/icons/failtile.png new file mode 100644 index 0000000000000000000000000000000000000000..4e1fdced2f3705fc712d589d318a116a7aa41ef2 GIT binary patch literal 4011 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 contributors' -}).addTo(mymap); +GetMapLayers(); +function GetMapLayers() { + var layergetter = new XMLHttpRequest(); + layergetter.onreadystatechange = function () { + if (layergetter.readyState === 4 && layergetter.status === 200) { + var maps = JSON.parse(layergetter.responseText); + var i = 0; + for (var key in maps) { + i++; + } + if (i === 1) { + L.tileLayer(maps["online"]["url"], { + attribution: maps["online"]["attribution"], + minZoom: maps["online"]["minZoom"], + maxZoom: maps["online"]["maxZoom"] + }).addTo(mymap); + } else { + var baseMaps = {}; + for (key in maps) { + if (key !== "online") { + var basemap = L.tileLayer(maps[key]["url"], { + attribution: maps[key]["attribution"], + minZoom: maps[key]["minZoom"], + maxZoom: maps[key]["maxZoom"], + errorTileUrl: "css/icons/failtile.png" + }); + basemap.addTo(mymap); + baseMaps[maps[key]["title"]] = basemap; + break; + } + } + for (key in maps) { + if (!baseMaps.hasOwnProperty(maps[key]["title"])) { + baseMaps[maps[key]["title"]] = L.tileLayer(maps[key]["url"], { + attribution: maps[key]["attribution"], + minZoom: maps[key]["minZoom"], + maxZoom: maps[key]["maxZoom"], + errorTileUrl: "css/icons/failtile.png" + }); + } + } + L.control.layers(baseMaps).addTo(mymap); + } + } + }; + layergetter.open("GET", "http://{%REQUEST_URL_HOST%}/getlayer", true); + layergetter.send(); +} mymap.on("click", hidePanel);