openwebrx-clone/owrx/map.py

109 lines
3.1 KiB
Python
Raw Normal View History

2019-07-07 13:52:24 +00:00
from datetime import datetime, timedelta
import threading, time
from owrx.config import PropertyManager
from owrx.bands import Band
2019-07-07 13:52:24 +00:00
import logging
logger = logging.getLogger(__name__)
class Location(object):
def __dict__(self):
return {}
class Map(object):
sharedInstance = None
@staticmethod
def getSharedInstance():
if Map.sharedInstance is None:
Map.sharedInstance = Map()
return Map.sharedInstance
def __init__(self):
self.clients = []
self.positions = {}
2019-07-07 13:52:24 +00:00
def removeLoop():
while True:
try:
self.removeOldPositions()
except Exception:
logger.exception("error while removing old map positions")
time.sleep(60)
threading.Thread(target=removeLoop, daemon=True).start()
super().__init__()
def broadcast(self, update):
for c in self.clients:
c.write_update(update)
def addClient(self, client):
self.clients.append(client)
2019-07-07 13:52:24 +00:00
client.write_update([
{
"callsign": callsign,
"location": record["location"].__dict__(),
2019-07-11 21:40:09 +00:00
"lastseen": record["updated"].timestamp() * 1000,
"mode" : record["mode"],
"band" : record["band"].getName() if record["band"] is not None else None
2019-07-07 13:52:24 +00:00
}
for (callsign, record) in self.positions.items()
])
def removeClient(self, client):
try:
self.clients.remove(client)
except ValueError:
pass
def updateLocation(self, callsign, loc: Location, mode: str, band: Band = None):
2019-07-07 13:52:24 +00:00
ts = datetime.now()
self.positions[callsign] = {"location": loc, "updated": ts, "mode": mode, "band": band}
2019-07-07 13:52:24 +00:00
self.broadcast([
{
"callsign": callsign,
"location": loc.__dict__(),
2019-07-11 21:40:09 +00:00
"lastseen": ts.timestamp() * 1000,
"mode" : mode,
"band" : band.getName() if band is not None else None
2019-07-07 13:52:24 +00:00
}
])
def removeLocation(self, callsign):
self.positions.pop(callsign, None)
# TODO broadcast removal to clients
def removeOldPositions(self):
pm = PropertyManager.getSharedInstance()
retention = timedelta(seconds=pm["map_position_retention_time"])
cutoff = datetime.now() - retention
2019-07-07 13:52:24 +00:00
to_be_removed = [callsign for (callsign, pos) in self.positions.items() if pos["updated"] < cutoff]
for callsign in to_be_removed:
self.removeLocation(callsign)
class LatLngLocation(Location):
def __init__(self, lat: float, lon: float):
self.lat = lat
self.lon = lon
def __dict__(self):
return {
"type":"latlon",
"lat":self.lat,
"lon":self.lon
}
class LocatorLocation(Location):
def __init__(self, locator: str):
self.locator = locator
def __dict__(self):
return {
"type":"locator",
"locator":self.locator
}