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 .zmsg import Bcast, Report, Resp, topic
14 log = getLogger("loctrkd/rectifier")
17 def runserver(conf: ConfigParser) -> None:
18 qry = import_module("." + conf.get("rectifier", "lookaside"), __package__)
20 proto_needanswer = dict(common.exposed_protos())
21 # Is this https://github.com/zeromq/pyzmq/issues/1627 still not fixed?!
22 zctx = zmq.Context() # type: ignore
23 zsub = zctx.socket(zmq.SUB) # type: ignore
24 zsub.connect(conf.get("collector", "publishurl"))
25 for proto in proto_needanswer.keys():
26 zsub.setsockopt(zmq.SUBSCRIBE, topic(proto))
27 zpush = zctx.socket(zmq.PUSH) # type: ignore
28 zpush.connect(conf.get("collector", "listenurl"))
29 zpub = zctx.socket(zmq.PUB) # type: ignore
30 zpub.connect(conf.get("rectifier", "publishurl"))
34 zmsg = Bcast(zsub.recv())
35 msg = common.parse_message(
36 zmsg.proto, zmsg.packet, is_incoming=zmsg.is_incoming
39 "IMEI %s from %s at %s: %s",
42 datetime.fromtimestamp(zmsg.when).astimezone(tz=timezone.utc),
45 rect = msg.rectified()
46 log.debug("rectified: %s", rect)
47 if rect.type == "approximate_location":
49 lat, lon = qry.lookup(
50 rect.mcc, rect.mnc, rect.base_stations, rect.wifi_aps
54 when=zmsg.when, # not the current time, but the original!
55 packet=msg.Out(latitude=lat, longitude=lon).packed,
58 "Response for lat=%s, lon=%s: %s", lat, lon, resp
60 zpush.send(resp.packed)
61 except Exception as e:
62 log.warning("Lookup for %s resulted in %s", msg, e)
64 except KeyboardInterrupt:
68 zctx.destroy() # type: ignore
72 if __name__.endswith("__main__"):
73 runserver(common.init(log))