1 """ Estimate coordinates from WIFI_POSITIONING and send back """
3 from configparser import ConfigParser
4 from datetime import datetime, timezone
5 from importlib import import_module
6 from logging import getLogger
8 from struct import pack
12 from .common import CoordReport, HintReport, StatusReport, Report
13 from .zmsg import Bcast, Rept, Resp, topic
15 log = getLogger("loctrkd/rectifier")
18 def runserver(conf: ConfigParser) -> None:
19 qry = import_module("." + conf.get("rectifier", "lookaside"), __package__)
21 proto_needanswer = dict(common.exposed_protos())
22 # Is this https://github.com/zeromq/pyzmq/issues/1627 still not fixed?!
23 zctx = zmq.Context() # type: ignore
24 zsub = zctx.socket(zmq.SUB) # type: ignore
25 zsub.connect(conf.get("collector", "publishurl"))
26 for proto in proto_needanswer.keys():
27 zsub.setsockopt(zmq.SUBSCRIBE, topic(proto))
28 zpush = zctx.socket(zmq.PUSH) # type: ignore
29 zpush.connect(conf.get("collector", "listenurl"))
30 zpub = zctx.socket(zmq.PUB) # type: ignore
31 zpub.connect(conf.get("rectifier", "publishurl"))
35 zmsg = Bcast(zsub.recv())
36 msg = common.parse_message(
37 zmsg.proto, zmsg.packet, is_incoming=zmsg.is_incoming
40 "IMEI %s from %s at %s: %s",
43 datetime.fromtimestamp(zmsg.when).astimezone(tz=timezone.utc),
46 rect: Report = msg.rectified()
47 log.debug("rectified: %s", rect)
48 if isinstance(rect, (CoordReport, StatusReport)):
49 zpub.send(Rept(imei=zmsg.imei, payload=rect.json).packed)
50 elif isinstance(rect, HintReport):
52 lat, lon = qry.lookup(
53 rect.mcc, rect.mnc, rect.gsm_cells, rect.wifi_aps
56 "Approximated lat=%s, lon=%s for %s", lat, lon, rect
58 if proto_needanswer.get(zmsg.proto, False):
61 when=zmsg.when, # not the current time, but the original!
62 packet=msg.Out(latitude=lat, longitude=lon).packed,
64 log.debug("Sending reponse %s", resp)
65 zpush.send(resp.packed)
71 battery_percentage=rect.battery_percentage,
81 except Exception as e:
83 "Lookup for %s rectified as %s resulted in %s",
89 except KeyboardInterrupt:
93 zctx.destroy() # type: ignore
97 if __name__.endswith("__main__"):
98 runserver(common.init(log))