Skip to content

Commit 0402979

Browse files
committed
Initial commit
0 parents  commit 0402979

21 files changed

Lines changed: 4906 additions & 0 deletions

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
node_modules
2+
.dist
3+
/dist
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
.pnpm-debug.log*
8+
.DS_Store
9+
.vscode
10+
.idea
11+
*.tsbuildinfo

gateway-map.js

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
class Map {
2+
constructor() {
3+
this.gateways = [];
4+
this.gatewaysCluster = this.initMarkerClusterGroup();
5+
this.theThingsNetworkCluster = this.initMarkerClusterGroup();
6+
this.privateNetworksCluster = this.initMarkerClusterGroup();
7+
this.showThingsStack = true;
8+
this.showPrivateNetworks = true;
9+
this.map = null;
10+
this.map = this.initMap();
11+
this.map.scrollWheelZoom.disable();
12+
this.onlineIcon = this.initIcon();
13+
}
14+
15+
initIcon() {
16+
return L.icon({
17+
iconUrl: document.currentScript.getAttribute("data-path-icon-gateway"),
18+
iconSize: [10, 20],
19+
});
20+
}
21+
22+
initMap() {
23+
if (this.map) {
24+
return this.map;
25+
}
26+
else {
27+
return L.map("map-wrap", {
28+
attributionControl: true,
29+
zoomControl: true,
30+
worldCopyJump: true,
31+
preferCanvas: true,
32+
}).setView(L.latLng(25, 0), 2);
33+
}
34+
}
35+
36+
initMarkerClusterGroup() {
37+
return L.markerClusterGroup({
38+
maxClusterRadius: 30,
39+
chunkedLoading: true,
40+
iconCreateFunction: function (cluster) {
41+
return L.divIcon({
42+
className: "gateways-cluster-icon",
43+
html: cluster.getChildCount(),
44+
});
45+
},
46+
});
47+
}
48+
49+
labelDict(arg) {
50+
return {
51+
"map.name": "Gateway name:",
52+
"map.id": "Gateway ID:",
53+
"map.unknown": "Unkown"
54+
}[arg];
55+
}
56+
57+
popupContent(gateway) {
58+
let content = {};
59+
// Commented out till packet broker api gives the name as well
60+
// content[this.labelDict("map.name")] = gateway.name;
61+
content[this.labelDict("map.id")] = gateway.id;
62+
let result = "";
63+
for (let key in content) {
64+
result +=
65+
"<b>" +
66+
key +
67+
"</b> " +
68+
(content[key] === undefined ? this.labelDict("map.unknown") : content[key]) +
69+
"<br />";
70+
}
71+
return result;
72+
}
73+
74+
createMapLayer(gatewaysList, gatewaysClusterList) {
75+
for (let key in gatewaysList) {
76+
let gateway = gatewaysList[key];
77+
if (gateway.hasOwnProperty("location") && gateway.online) {
78+
let marker = L.marker(
79+
[gateway.location.latitude, gateway.location.longitude],
80+
{ icon: this.onlineIcon }
81+
);
82+
marker.bindPopup(this.popupContent(gateway));
83+
gatewaysClusterList.addLayer(marker);
84+
}
85+
}
86+
return gatewaysClusterList;
87+
}
88+
89+
initMapLayers() {
90+
let theThingsNetwork = this.gateways.filter(gateway => (gateway.tenantID === "ttn" || gateway.tenantID === "ttnv2"));
91+
let privateNetworks = this.gateways.filter(gateway => (gateway.tenantID !== "ttn" && gateway.tenantID !== "ttnv2"));
92+
93+
this.gatewaysCluster = this.createMapLayer(this.gateways, this.gatewaysCluster);
94+
this.theThingsNetworkCluster = this.createMapLayer(theThingsNetwork, this.theThingsNetworkCluster);
95+
this.privateNetworksCluster = this.createMapLayer(privateNetworks, this.privateNetworksCluster);
96+
97+
this.map.addLayer(this.gatewaysCluster);
98+
}
99+
100+
createPacketBrokerAnchorTag() {
101+
let packetBrokerTag = document.createElement('a');
102+
103+
packetBrokerTag.setAttribute('href', 'https://packetbroker.net/');
104+
packetBrokerTag.setAttribute('class', 'packet-broker-link leaflet-control');
105+
packetBrokerTag.setAttribute('target', '_blank');
106+
packetBrokerTag.innerText = this.gateways.length + " gateways are connected via Packet Broker";
107+
return packetBrokerTag;
108+
}
109+
110+
addPacketBrokerText() {
111+
let packetBrokerTag = this.createPacketBrokerAnchorTag();
112+
let packetBrokerTag2 = this.createPacketBrokerAnchorTag();
113+
114+
packetBrokerTag2.setAttribute('class', 'packet-broker-mobile');
115+
116+
document.getElementById("packet-broker-id-desktop").appendChild(packetBrokerTag);
117+
document.getElementById("packet-broker-id-mobile").appendChild(packetBrokerTag2);
118+
}
119+
120+
changeMapLayers() {
121+
this.map.removeLayer(this.gatewaysCluster);
122+
if (this.showThingsStack && this.showPrivateNetworks) {
123+
this.map.addLayer(this.gatewaysCluster);
124+
return;
125+
}
126+
(this.showPrivateNetworks)
127+
? this.map.addLayer(this.privateNetworksCluster)
128+
: this.map.removeLayer(this.privateNetworksCluster);
129+
(this.showThingsStack)
130+
? this.map.addLayer(this.theThingsNetworkCluster)
131+
: this.map.removeLayer(this.theThingsNetworkCluster);
132+
}
133+
134+
addReferences() {
135+
L.tileLayer("https://{s}.tile.osm.org/{z}/{x}/{y}.png", {
136+
detectRetina: true,
137+
maxNativeZoom: 17,
138+
attribution: '© <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a> contributors',
139+
}).addTo(this.map);
140+
141+
let attributions = document.getElementsByClassName('leaflet-control-attribution')
142+
for (let index = 0; index < attributions.length; ++index) {
143+
attributions[index].innerHTML = '<a href="https://leafletjs.com" title="A JS library for interactive maps" target="_blank">Leaflet</a> | © <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a> contributors';
144+
}
145+
}
146+
147+
addSearch() {
148+
const provider = new window.GeoSearch.OpenStreetMapProvider();
149+
const search = new GeoSearch.GeoSearchControl({
150+
provider: provider,
151+
style: 'bar',
152+
updateMap: true,
153+
autoClose: true,
154+
});
155+
search.addTo(this.map);
156+
}
157+
}
158+
159+
(function(){
160+
let mapClass = new Map();
161+
162+
mapClass.addReferences();
163+
mapClass.addSearch();
164+
165+
fetch("https://mapper.packetbroker.net/api/v2/gateways")
166+
.then(function (response) {
167+
return response.json();
168+
})
169+
.then(function (gateways) {
170+
document.getElementById('loading').remove();
171+
if (gateways === null) {
172+
return;
173+
}
174+
mapClass.gateways = gateways;
175+
mapClass.addPacketBrokerText();
176+
mapClass.initMapLayers();
177+
});
178+
179+
const thingsStackBtnClick = () => {
180+
mapClass.showThingsStack = !mapClass.showThingsStack;
181+
mapClass.changeMapLayers();
182+
}
183+
184+
const privateNetBtnClick = () => {
185+
mapClass.showPrivateNetworks = !mapClass.showPrivateNetworks;
186+
mapClass.changeMapLayers();
187+
}
188+
189+
document.getElementById("ThingsStackBtnDropdown").addEventListener("click", thingsStackBtnClick);
190+
document.getElementById("PrivateNetBtnDropdown").addEventListener("click", privateNetBtnClick);
191+
document.getElementById("ThingsStackBtn").addEventListener("click", thingsStackBtnClick);
192+
document.getElementById("PrivateNetBtn").addEventListener("click", privateNetBtnClick);
193+
})();
194+
195+
document.getElementById("dropdownBtn").addEventListener("click", function() {
196+
document.getElementById("dropdownId").classList.toggle("show");
197+
document.getElementById("filter-icon").classList.toggle("hide");
198+
document.getElementById("close-icon").classList.toggle("hide");
199+
});

index.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>TTN Mapper</title>
7+
<link rel="preconnect" href="https://fonts.googleapis.com" />
8+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9+
<link
10+
href="https://fonts.googleapis.com/css2?family=League+Spartan:wght@400;500;600;700&family=Lato:wght@400;600;700;900&display=swap"
11+
rel="stylesheet"
12+
/>
13+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
14+
</head>
15+
<body class="bg-midnight text-white">
16+
<div id="root"></div>
17+
<script type="module" src="/src/main.tsx"></script>
18+
</body>
19+
</html>

map.html

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
2+
<!DOCTYPE html>
3+
<html lang="en" prefix="og: http://ogp.me/ns#" class="ttui-disable-font-smoothing">
4+
<head>
5+
<!-- Google Tag Manager -->
6+
<script async src="/static/common/js/gt.89450084d2c5.js"></script>
7+
<!-- End Google Tag Manager -->
8+
9+
<title>The Things Network</title>
10+
11+
<!-- META -->
12+
<meta charset="UTF-8">
13+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
14+
<meta name="author" content="The Things Network">
15+
<meta name="description" content="The Things Network">
16+
<meta name="keywords" content="lorawan, lora, internet of things, iot, the things network">
17+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
18+
<meta name="google-site-verification" content="cfDbRAW2LRts8AeU8Zsd-4ESMGj-HUpf40tmybcSCpE" />
19+
20+
<!-- OPEN GRAPH -->
21+
<meta property="og:site_name" content="The Things Network" />
22+
23+
<meta property="og:url" content="https://www.thethingsnetwork.org/map" />
24+
25+
<meta property="og:type" content="website" />
26+
27+
<meta property="og:title" content="The Things Network" />
28+
<meta property="og:description" content="We are building a global open free crowdsourced long range low battery IoT data network." />
29+
30+
<meta property="og:image" content="/static/common/img/ttn-thumbnail.ac06b96f3e64.png" />
31+
32+
33+
34+
<!-- Google Structured Data -->
35+
<script type="application/ld+json">
36+
{
37+
"@context": "https://schema.org",
38+
"@type": "Organization",
39+
"name": "The Things Network",
40+
"description": "We are building a global open free crowdsourced long range low power IoT data network.",
41+
"url": "https://www.thethingsnetwork.org/",
42+
"logo": "https://www.thethingsnetwork.org/spa/static/img/b403019.png",
43+
"sameAs": [
44+
"https://www.facebook.com/thethingsnetwork/",
45+
"https://www.instagram.com/thethingsntwrk/",
46+
"https://www.linkedin.com/company/the-things-network/",
47+
"https://twitter.com/thethingsntwrk",
48+
"https://www.youtube.com/channel/UCv85CXnZUXEKnlZpQapTAwQ"
49+
]
50+
}
51+
</script>
52+
<script src="/static/common/dist/js/main.de878e1330e4.js"></script>
53+
54+
<!-- Favicons -->
55+
<link rel="apple-touch-icon-precomposed" href="/static/common/favicon/favicon-152.6c70a98e264d.png">
56+
57+
<meta name="msapplication-TileColor" content="#FFFFFF">
58+
<meta name="msapplication-TileImage" content="/static/common/favicon/favicon-144.61bd01a950fb.png">
59+
60+
<meta name="application-name" content="The Things Network">
61+
<meta name="msapplication-tooltip" content="Tooltip">
62+
<meta name="msapplication-config" content="/static/common/favicon/ieconfig.54334a5ee30c.xml">
63+
64+
<link rel="icon" href="/static/common/favicon/favicon-32.61b30f85680a.png" sizes="32x32">
65+
<link rel="icon" href="/static/common/favicon/favicon-57.83b86c64dc82.png" sizes="57x57">
66+
<link rel="icon" href="/static/common/favicon/favicon-76.7dcf8fa36dfc.png" sizes="76x76">
67+
<link rel="icon" href="/static/common/favicon/favicon-96.27ac17adaa8b.png" sizes="96x96">
68+
<link rel="icon" href="/static/common/favicon/favicon-120.e1526731335e.png" sizes="120x120">
69+
<link rel="icon" href="/static/common/favicon/favicon-128.fabea041224c.png" sizes="128x128">
70+
<link rel="icon" href="/static/common/favicon/favicon-144.61bd01a950fb.png" sizes="144x144">
71+
<link rel="icon" href="/static/common/favicon/favicon-152.6c70a98e264d.png" sizes="152x152">
72+
<link rel="icon" href="/static/common/favicon/favicon-180.fcd414307ca3.png" sizes="180x180">
73+
<link rel="icon" href="/static/common/favicon/favicon-195.c55ce09d66da.png" sizes="195x195">
74+
<link rel="icon" href="/static/common/favicon/favicon-228.bea53ec4b10b.png" sizes="228x228">
75+
<link rel="icon" href="/static/common/favicon/smalltile.fabea041224c.png" sizes="128x128">
76+
<link rel="icon" href="/static/common/favicon/mediumtile.3d42f7faac82.png" sizes="270x270">
77+
<link rel="icon" href="/static/common/favicon/widetile.3d42f7faac82.png" sizes="558x270">
78+
<link rel="icon" href="/static/common/favicon/largetile.eb144ebab4d1.png" sizes="558x558">
79+
<link rel="shortcut icon" sizes="196x196" href="/static/common/favicon/favicon-196.277278d69ddc.png">
80+
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Lato:400,700,900"/>
81+
<link rel="stylesheet" type="text/css" href="/static/common/css/ionicons.min.7b268418a9fe.css"/>
82+
<link rel="stylesheet" type="text/css" href="/static/common/css/animate.min.178b651958ce.css"/>
83+
84+
<link rel="stylesheet" type="text/css" href="/static/common/css/bootstrap.096e6546405f.css"/>
85+
86+
<link rel="stylesheet" type="text/css" href="/static/common/dist/css/main.ee16f81054db.css"/>
87+
88+
89+
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/>
90+
<link rel="stylesheet" href="https://unpkg.com/leaflet-geosearch@3.1.0/dist/geosearch.css"/>
91+
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.4.1/dist/MarkerCluster.css" />
92+
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
93+
94+
95+
</head>
96+
<body class="theme-ttn">
97+
<ttui-cookie id="cookie-banner"></ttui-cookie>
98+
99+
<ttn-header></ttn-header>
100+
101+
102+
103+
104+
<div class="ttn-map">
105+
<div class="ttn-map map" id="map-div">
106+
<div class="packet-broker-mobile" id="packet-broker-id-mobile"></div>
107+
<div class="dropdown">
108+
<button id="dropdownBtn" class="dropbtn">Filters <span id="filter-icon" class="material-icons">filter_list</span><span id="close-icon" class="material-icons hide">close</span></button>
109+
<div id="dropdownId" class="dropdown-content">
110+
<div><input type="checkbox" id="ThingsStackBtnDropdown" value="The Things Stack Community Edition" class="checkbox leaflet-control" checked/><p class="checkbox-text">The Things Stack Community Edition</p></div>
111+
<div><input type="checkbox" id="PrivateNetBtnDropdown" value="Interconnected private networks" class="checkbox leaflet-control" checked/><p class="checkbox-text">Interconnected private networks</p></div>
112+
113+
</div>
114+
</div>
115+
<div class="loading-div" id="loading">
116+
<div class="spinner-container">
117+
<div class="spinner">
118+
</div>
119+
</div>
120+
</div>
121+
<div id="map-wrap">
122+
<div class="leaflet-bottom leaflet-right packet-broker-div" id="packet-broker-id-desktop"></div>
123+
<div class="leaflet-bottom leaflet-left filter-div">
124+
<div><p class="checkbox-header-text">Display gateways:</p></div>
125+
<div><input type="checkbox" id="ThingsStackBtn" value="The Things Stack Community Edition" class="checkbox leaflet-control" checked/><p class="checkbox-text">The Things Stack Community Edition</p></div>
126+
<div><input type="checkbox" id="PrivateNetBtn" value="Interconnected private networks" class="checkbox leaflet-control" checked/><p class="checkbox-text">Interconnected private networks</p></div>
127+
128+
</div>
129+
</div>
130+
</div>
131+
</div>
132+
133+
134+
<div class="ttn-footer"><div class="ttui-container ttn-footer__wrapper"><ttn-footer class="theme-ttn"></ttn-footer></div></div>
135+
136+
<script src="/static/common/js/jquery-2.1.3.0bdc04968d2f.js"></script>
137+
138+
<script src="/static/common/js/cookie.591afde2c690.js"></script>
139+
<script src="/static/common/js/bootstrap.2e4e51c14940.js"></script>
140+
<script src="/static/common/js/bootstrap-notify.min.35eb2c218552.js"></script>
141+
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@7/dist/polyfill.min.js"></script>
142+
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.min.js"></script>
143+
144+
145+
146+
147+
<script type="text/javascript" src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
148+
<script type="text/javascript" src="https://unpkg.com/leaflet.markercluster@1.4.1/dist/leaflet.markercluster.js"></script>
149+
<script src="https://unpkg.com/leaflet-geosearch@3.1.0/dist/bundle.min.js"></script>
150+
<script type="text/javascript" src="/static/ttn/js/gateway-map.148d596c9eb5.js" data-path-icon-gateway="/static/ttn/image/map/marker.25e31a868ce4.svg"> </script>
151+
152+
</body>
153+
</html>

0 commit comments

Comments
 (0)