1<!-- 2Copyright 2022 Google LLC 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 https://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15--> 16 17<link rel="preconnect" href="https://fonts.googleapis.com" /> 18<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> 19<link 20 href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;700&display=swap" 21 rel="stylesheet" 22/> 23 24<style> 25 body { 26 margin: 0; 27 background: var(--background); 28 font-family: "Montserrat", sans-serif; 29 } 30 31 main { 32 display: flex; 33 flex-direction: row; 34 width: 100vw; 35 height: 100vh; 36 } 37 38 #map { 39 width: var(--map-size); 40 } 41 42 #info { 43 width: 400px; 44 background: var(--sidebar-color); 45 box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23); 46 } 47 48 :root { 49 --map-size: calc(100vw - 400px); 50 --background: #cbd5e1; 51 --grid-line-color: #fbbf24; 52 --grid-background-color: #f8fafc; 53 --sidebar-color: #ea8ca8; 54 --selection-color: #f0abfc; 55 } 56</style> 57<main> 58 <pika-map id="map"></pika-map> 59 <pika-device-info id="info"></pika-device-info> 60</main> 61 62<script type="importmap"> 63 { 64 "imports": { 65 "lit": "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js" 66 } 67 } 68</script> 69 70<script type="module"> 71 import { LitElement, html } from "lit"; 72 73 import "./src/components/Map.js"; 74 import "./src/components/DeviceInfo.js"; 75 76 const map = document.getElementById("map"); 77 const info = document.getElementById("info"); 78 79 map.addEventListener( 80 "select", 81 (event) => (info.device = event.detail.device) 82 ); 83 84 map.addEventListener("move", () => info.update()); 85 86 function set_position({ 87 mac_address, 88 position: { x, y, z }, 89 yaw, 90 pitch, 91 roll, 92 }) { 93 const path = "/set-position/" + mac_address; 94 fetch(path, { 95 method: "POST", 96 headers: { 97 "content-type": "application/json", 98 }, 99 body: JSON.stringify({ 100 x, 101 y, 102 z, 103 yaw, 104 pitch, 105 roll, 106 }), 107 }); 108 } 109 110 map.addEventListener("end-move", (event) => { 111 set_position(event.detail.device); 112 }); 113 114 info.addEventListener("orientation-change", () => { 115 console.log("Orientation change"); 116 set_position(info.device); 117 }); 118 119 const events = new EventSource("/events"); 120 121 events.addEventListener("device-added", (event) => { 122 const data = JSON.parse(event.data); 123 console.log("Device Added", data); 124 125 const { 126 mac_address, x, y, z, yaw, pitch, roll, 127 } = data; 128 map.devices = [ 129 ...map.devices, 130 { 131 mac_address, 132 position: { x, y, z }, 133 yaw, 134 pitch, 135 roll, 136 neighbors: [], 137 }, 138 ]; 139 }); 140 141 events.addEventListener("device-removed", (event) => { 142 const data = JSON.parse(event.data); 143 console.log("Device Removed", data); 144 145 const { 146 mac_address, 147 } = data; 148 if (info.device?.mac_address === mac_address) { 149 info.device = null; 150 } 151 152 map.devices = map.devices.filter( 153 (device) => device.mac_address !== mac_address 154 ); 155 156 map.devices.forEach((device) => { 157 device.neighbors = device.neighbors.filter( 158 (neighbor) => neighbor.mac_address !== mac_address 159 ); 160 }); 161 }); 162 163 events.addEventListener("position-updated", (event) => { 164 const data = JSON.parse(event.data); 165 console.log("Position updated", data); 166 167 const { 168 mac_address, x, y, z, yaw, pitch, roll, 169 } = data; 170 171 const device = map.devices.find( 172 (device) => device.mac_address === mac_address 173 ); 174 175 device.position = { x, y, z }; 176 device.yaw = yaw; 177 device.pitch = pitch; 178 device.roll = roll; 179 180 map.update(); 181 info.update(); 182 }); 183 184 events.addEventListener("neighbor-updated", (event) => { 185 const data = JSON.parse(event.data); 186 console.log("Neighbor updated", data); 187 188 const { 189 source_mac_address, 190 destination_mac_address, 191 distance, 192 azimuth, 193 elevation, 194 } = data; 195 196 const device = map.devices.find( 197 (device) => device.mac_address === source_mac_address 198 ); 199 200 const neighbor = device.neighbors.find( 201 (device) => device.mac_address == destination_mac_address 202 ) || { mac_address: destination_mac_address }; 203 204 neighbor.distance = distance; 205 neighbor.azimuth = azimuth; 206 neighbor.elevation = elevation; 207 208 if (!device.neighbors.includes(neighbor)) device.neighbors.push(neighbor); 209 210 info.update(); 211 }); 212</script> 213