X-Git-Url: http://www.average.org/gitweb/?p=loctrkd.git;a=blobdiff_plain;f=loctrkd%2Frectifier.py;h=5926377ee76ad4dc5665b72dec551a5e279bc661;hp=8ee75970aec030f771ec0555ba306ad68b1a3397;hb=2cf0fd9d215dda17eae4261ab7967367f6aa0028;hpb=16bea55924c0ab9d035f3e99573fc49c370de231 diff --git a/loctrkd/rectifier.py b/loctrkd/rectifier.py index 8ee7597..5926377 100644 --- a/loctrkd/rectifier.py +++ b/loctrkd/rectifier.py @@ -6,32 +6,61 @@ from importlib import import_module from logging import getLogger from os import umask from struct import pack +from typing import cast, List, Tuple import zmq from . import common -from .zx303proto import parse_message, proto_name, WIFI_POSITIONING -from .zmsg import Bcast, Resp, topic +from .common import CoordReport, HintReport, StatusReport, Report +from .zmsg import Bcast, Rept, Resp, topic log = getLogger("loctrkd/rectifier") +class QryModule: + @staticmethod + def init(conf: ConfigParser) -> None: + ... + + @staticmethod + def shut() -> None: + ... + + @staticmethod + def lookup( + mcc: int, + mnc: int, + gsm_cells: List[Tuple[int, int, int]], + wifi_aps: List[Tuple[str, int]], + ) -> Tuple[float, float, float]: + ... + + def runserver(conf: ConfigParser) -> None: - qry = import_module("." + conf.get("rectifier", "lookaside"), __package__) + qry = cast( + QryModule, + import_module("." + conf.get("rectifier", "lookaside"), __package__), + ) qry.init(conf) + proto_needanswer = dict(common.exposed_protos()) # Is this https://github.com/zeromq/pyzmq/issues/1627 still not fixed?! zctx = zmq.Context() # type: ignore zsub = zctx.socket(zmq.SUB) # type: ignore zsub.connect(conf.get("collector", "publishurl")) - zsub.setsockopt(zmq.SUBSCRIBE, topic(proto_name(WIFI_POSITIONING))) + for proto in proto_needanswer.keys(): + zsub.setsockopt(zmq.SUBSCRIBE, topic(proto)) zpush = zctx.socket(zmq.PUSH) # type: ignore zpush.connect(conf.get("collector", "listenurl")) zpub = zctx.socket(zmq.PUB) # type: ignore - zpub.connect(conf.get("rectifier", "publishurl")) + oldmask = umask(0o117) + zpub.bind(conf.get("rectifier", "publishurl")) + umask(oldmask) try: while True: zmsg = Bcast(zsub.recv()) - msg = parse_message(zmsg.packet) + msg = common.parse_message( + zmsg.proto, zmsg.packet, is_incoming=zmsg.is_incoming + ) log.debug( "IMEI %s from %s at %s: %s", zmsg.imei, @@ -39,19 +68,59 @@ def runserver(conf: ConfigParser) -> None: datetime.fromtimestamp(zmsg.when).astimezone(tz=timezone.utc), msg, ) - try: - lat, lon = qry.lookup( - msg.mcc, msg.mnc, msg.gsm_cells, msg.wifi_aps - ) - resp = Resp( - imei=zmsg.imei, - when=zmsg.when, # not the current time, but the original! - packet=msg.Out(latitude=lat, longitude=lon).packed, + pmod, rect = msg.rectified() + log.debug("rectified: %s", rect) + if isinstance(rect, (CoordReport, StatusReport)): + zpub.send( + Rept(imei=zmsg.imei, pmod=pmod, payload=rect.json).packed ) - log.debug("Response for lat=%s, lon=%s: %s", lat, lon, resp) - zpush.send(resp.packed) - except Exception as e: - log.warning("Lookup for %s resulted in %s", msg, e) + elif isinstance(rect, HintReport): + try: + lat, lon, acc = qry.lookup( + rect.mcc, + rect.mnc, + rect.gsm_cells, + list((mac, strng) for _, mac, strng in rect.wifi_aps), + ) + log.debug( + "Approximated lat=%s, lon=%s, acc=%s for %s", + lat, + lon, + acc, + rect, + ) + if proto_needanswer.get(zmsg.proto, False): + resp = Resp( + imei=zmsg.imei, + when=zmsg.when, # not the current time, but the original! + packet=msg.Out(latitude=lat, longitude=lon).packed, + ) + log.debug("Sending reponse %s", resp) + zpush.send(resp.packed) + rept = CoordReport( + devtime=rect.devtime, + battery_percentage=rect.battery_percentage, + accuracy=acc, + altitude=None, + speed=None, + direction=None, + latitude=lat, + longitude=lon, + ) + log.debug("Sending report %s", rept) + zpub.send( + Rept( + imei=zmsg.imei, + payload=rept.json, + ).packed + ) + except Exception as e: + log.exception( + "Lookup for %s rectified as %s resulted in %s", + msg, + rect, + e, + ) except KeyboardInterrupt: zsub.close()