14 changed files with 207 additions and 4 deletions
@ -0,0 +1,44 @@ |
|||
import aiohttp |
|||
from pymongo.asynchronous.database import AsyncDatabase |
|||
|
|||
from logger import logger |
|||
from time import time |
|||
|
|||
class TileManager: |
|||
domain = 'a.tile.openstreetmap.org' |
|||
format = "png" |
|||
|
|||
def __init__(self, core): |
|||
self.core = core |
|||
self.dbStore:AsyncDatabase = self.core.dbStore |
|||
|
|||
def generateHeaders(self): |
|||
return { |
|||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", |
|||
"Referer": "http://localhost:4200/", |
|||
"Accept": "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8" |
|||
} |
|||
|
|||
async def grabTile(self, z:int, x:int, y:int): |
|||
#grab from db |
|||
collection = self.dbStore['openstreetmap'] |
|||
query = {"x":x, "y":y, "z": z} |
|||
t = await collection.find_one(query) |
|||
if t: |
|||
return t["img"] |
|||
else: |
|||
#ищем картинку чтож поделать |
|||
url = f"https://{self.domain}/{z}/{x}/{y}.{self.format}" |
|||
async with aiohttp.ClientSession() as session: |
|||
async with session.get(url, ssl=False, headers=self.generateHeaders()) as resp: |
|||
# Read the entire response body as bytes |
|||
img = await resp.read() |
|||
logger.info(url, resp.status) |
|||
if resp.status == 200: |
|||
query['ts'] = time() |
|||
query['img'] = img |
|||
query['format'] = self.format |
|||
await collection.insert_one(query) |
|||
return img |
|||
else: |
|||
raise Exception("cannot get img") |
|||
@ -0,0 +1,69 @@ |
|||
import {Component, OnInit} from "@angular/core"; |
|||
import * as L from 'leaflet'; |
|||
import {HttpClient} from "@angular/common/http"; |
|||
import {NodeDTO} from "../../entities/NodeDTO"; |
|||
import {Subscription} from "rxjs"; |
|||
|
|||
@Component({ |
|||
selector: "app-nodes-map", |
|||
styleUrls: ['nodes.styles.scss'], |
|||
template: ` |
|||
<div style="width:80%"> |
|||
<div class="map-container"> |
|||
<div class="map-frame"> |
|||
<div id="map"></div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
` |
|||
}) |
|||
export class NodesMapComponent implements OnInit { |
|||
map!: L.Map; |
|||
nodes: NodeDTO[] = [] |
|||
|
|||
constructor(private http: HttpClient) { |
|||
} |
|||
|
|||
ngOnInit(): void { |
|||
this.http.get(`api/nodes/list?p=true`).subscribe( |
|||
(obj) => { |
|||
this.nodes = (obj as NodeDTO[]) |
|||
} |
|||
).add( |
|||
() => { |
|||
|
|||
this.createMap(this.convertPosition(this.nodes.filter((node) => node.havePosition).pop())).add( |
|||
() => { |
|||
this.nodes.filter((node) => node.havePosition).forEach( |
|||
(node) => { |
|||
L.marker(this.convertPosition(node)).addTo(this.map) |
|||
} |
|||
) |
|||
} |
|||
) |
|||
} |
|||
) |
|||
} |
|||
|
|||
convertPosition(node:NodeDTO|undefined):[number, number] { |
|||
if (node) { |
|||
let lat = node.position.latitude_i / 10000000; |
|||
let lng = node.position.longitude_i / 10000000; |
|||
return [lat, lng]; |
|||
} else return [0,0]; |
|||
} |
|||
|
|||
createMap(center:[number, number]) { |
|||
this.map = L.map("map",{ |
|||
center: center, |
|||
zoom: 11 |
|||
}); |
|||
const tiles = L.tileLayer('api/tile/{z}/{x}/{y}.png', { |
|||
maxZoom: 18, |
|||
minZoom: 3, |
|||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>' |
|||
}); |
|||
tiles.addTo(this.map) |
|||
return Subscription.EMPTY; |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
.map-container { |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
margin: 30px; |
|||
} |
|||
|
|||
.map-frame { |
|||
border: 2px solid black; |
|||
height: 100%; |
|||
} |
|||
|
|||
#map { |
|||
height: 100%; |
|||
} |
|||
|
|||
:host ::ng-deep .leaflet-control-attribution { |
|||
display: none; |
|||
} |
|||
@ -1,7 +1,13 @@ |
|||
import {NodeMiniDTO} from "./NodeMiniDTO"; |
|||
import {PositionDTO} from "./node/PositionDTO"; |
|||
import {DeviceMetricsDTO} from "./node/DeviceMetricsDTO"; |
|||
|
|||
export interface NodeDTO extends NodeMiniDTO { |
|||
snr: number, |
|||
hops_away: number, |
|||
ts: number |
|||
havePosition:boolean, |
|||
position: PositionDTO, |
|||
haveMetrics:boolean, |
|||
device_metrics: DeviceMetricsDTO |
|||
} |
|||
|
|||
@ -0,0 +1,7 @@ |
|||
export interface DeviceMetricsDTO { |
|||
battery_level: number, |
|||
voltage: number, |
|||
channel_utilization: number, |
|||
air_util_tx: number, |
|||
uptime_seconds: number |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
export interface PositionDTO { |
|||
latitude_i: number, |
|||
longitude_i: number, |
|||
time: number, |
|||
location_source: number |
|||
} |
|||
Loading…
Reference in new issue