From: Eugene Crosser Date: Fri, 29 Jul 2022 20:38:35 +0000 (+0200) Subject: Cleanup some of the types X-Git-Tag: 1.90~5 X-Git-Url: http://www.average.org/gitweb/?p=loctrkd.git;a=commitdiff_plain;h=456fcc5a8964c84385d34a6687e83ae05ab2ddc3 Cleanup some of the types --- diff --git a/loctrkd/beesure.py b/loctrkd/beesure.py index ad351cb..b9b4639 100755 --- a/loctrkd/beesure.py +++ b/loctrkd/beesure.py @@ -39,7 +39,6 @@ __all__ = ( "proto_handled", "parse_message", "probe_buffer", - "proto_name", "DecodeError", "Respond", ) @@ -141,6 +140,14 @@ def enframe(buffer: bytes, imei: Optional[str] = None) -> bytes: ### Parser/Constructor ### +class classproperty: + def __init__(self, f: Callable[[Any], str]) -> None: + self.f = f + + def __get__(self, obj: Any, owner: Any) -> str: + return self.f(owner) + + class DecodeError(Exception): def __init__(self, e: Exception, **kwargs: Any) -> None: super().__init__(e) @@ -278,14 +285,21 @@ class BeeSurePkt(ProtoClass): # Overridden in subclasses, otherwise command verb only return "" - @property - def PROTO(self) -> str: + @classproperty + def PROTO(cls: "BeeSurePkt") -> str: + """Name of the class without possible .In / .Out suffix""" + proto: str try: - proto, _ = self.__class__.__name__.split(".") + proto, _ = cls.__name__.split(".") except ValueError: - proto = self.__class__.__name__ + proto = cls.__name__ return proto + @classmethod + def proto_name(cls) -> str: + """Name of the command as used externally""" + return PROTO_PREFIX + cls.PROTO[:16] + @property def packed(self) -> bytes: data = self.encode() @@ -553,12 +567,6 @@ def proto_handled(proto: str) -> bool: return proto.startswith(PROTO_PREFIX) -def proto_name(obj: Union[Type[BeeSurePkt], BeeSurePkt]) -> str: - return PROTO_PREFIX + ( - obj.__class__.__name__ if isinstance(obj, BeeSurePkt) else obj.__name__ - ) - - def proto_of_message(packet: bytes) -> str: return PROTO_PREFIX + packet[20:-1].split(b",")[0].decode() @@ -622,7 +630,7 @@ def parse_message(packet: bytes, is_incoming: bool = True) -> BeeSurePkt: def exposed_protos() -> List[Tuple[str, bool]]: return [ - (proto_name(cls)[:16], False) + (cls.proto_name(), False) for cls in CLASSES.values() if hasattr(cls, "rectified") ] diff --git a/loctrkd/common.py b/loctrkd/common.py index 30a1719..1257a72 100644 --- a/loctrkd/common.py +++ b/loctrkd/common.py @@ -80,9 +80,17 @@ def exposed_protos() -> List[Tuple[str, bool]]: return [item for pmod in pmods for item in pmod.exposed_protos()] -class Report(SimpleNamespace): +class Report: TYPE: str + def __repr__(self) -> str: + return ( + self.__class__.__name__ + + "(" + + ", ".join([f"{k}={v}" for k, v in self.__dict__.items()]) + + ")" + ) + @property def json(self) -> str: self.type = self.TYPE @@ -102,18 +110,16 @@ class CoordReport(Report): speed: float, direction: float, latitude: float, - longitude: float + longitude: float, ) -> None: - super().__init__( - devtime=devtime, - battery_percentage=battery_percentage, - accuracy=accuracy, - altitude=altitude, - speed=speed, - direction=direction, - latitude=latitude, - longitude=longitude, - ) + self.devtime = devtime + self.battery_percentage = battery_percentage + self.accuracy = accuracy + self.altitude = altitude + self.speed = speed + self.direction = direction + self.latitude = latitude + self.longitude = longitude class HintReport(Report): @@ -127,20 +133,18 @@ class HintReport(Report): mcc: int, mnc: int, gsm_cells: List[Tuple[int, int, int]], - wifi_aps: List[Tuple[str, str, int]] + wifi_aps: List[Tuple[str, str, int]], ) -> None: - super().__init__( - devtime=devtime, - battery_percentage=battery_percentage, - mcc=mcc, - mnc=mnc, - gsm_cells=gsm_cells, - wifi_aps=wifi_aps, - ) + self.devtime = devtime + self.battery_percentage = battery_percentage + self.mcc = mcc + self.mnc = mnc + self.gsm_cells = gsm_cells + self.wifi_aps = wifi_aps class StatusReport(Report): TYPE = "status" def __init__(self, *, battery_percentage: int) -> None: - super().__init__(battery_percentage=battery_percentage) + self.battery_percentage = battery_percentage diff --git a/loctrkd/googlemaps.py b/loctrkd/googlemaps.py index 881a2bd..5aace47 100644 --- a/loctrkd/googlemaps.py +++ b/loctrkd/googlemaps.py @@ -45,33 +45,3 @@ def lookup( return result["location"]["lat"], result["location"]["lng"] else: raise ValueError("google geolocation: " + str(result)) - - -if __name__.endswith("__main__"): - from datetime import datetime, timezone - from sqlite3 import connect - import sys - from .zx303proto import * - from .zx303proto import WIFI_POSITIONING, WIFI_OFFLINE_POSITIONING - - db = connect(sys.argv[1]) - c = db.cursor() - c.execute( - """select tstamp, packet from events - where proto in (?, ?)""", - (proto_name(WIFI_POSITIONING), proto_name(WIFI_OFFLINE_POSITIONING)), - ) - init({"googlemaps": {"accesstoken": sys.argv[2]}}) - count = 0 - for timestamp, packet in c: - obj = parse_message(packet) - print(obj) - avlat, avlon = lookup(obj.mcc, obj.mnc, obj.gsm_cells, obj.wifi_aps) - print( - "{} {:+#010.8g},{:+#010.8g}".format( - datetime.fromtimestamp(timestamp), avlat, avlon - ) - ) - count += 1 - if count > 10: - break diff --git a/loctrkd/opencellid.py b/loctrkd/opencellid.py index 4d0edce..22aedcf 100644 --- a/loctrkd/opencellid.py +++ b/loctrkd/opencellid.py @@ -52,27 +52,3 @@ def lookup( lc.execute("""detach database mem""") lc.close() return avlat, avlon - - -if __name__.endswith("__main__"): - from datetime import datetime, timezone - import sys - from .zx303proto import * - from .zx303proto import WIFI_POSITIONING, WIFI_OFFLINE_POSITIONING - - db = connect(sys.argv[1]) - c = db.cursor() - c.execute( - """select tstamp, packet from events - where proto in (?, ?)""", - (proto_name(WIFI_POSITIONING), proto_name(WIFI_OFFLINE_POSITIONING)), - ) - init({"opencellid": {"dbfn": sys.argv[2]}}) - for timestamp, packet in c: - obj = parse_message(packet) - avlat, avlon = lookup(obj.mcc, obj.mnc, obj.gsm_cells, obj.wifi_aps) - print( - "{} {:+#010.8g},{:+#010.8g}".format( - datetime.fromtimestamp(timestamp), avlat, avlon - ) - ) diff --git a/loctrkd/protomodule.py b/loctrkd/protomodule.py index 446fec6..1d61759 100644 --- a/loctrkd/protomodule.py +++ b/loctrkd/protomodule.py @@ -88,6 +88,10 @@ class ProtoClass(Protocol, metaclass=_MetaProto): IN_KWARGS: Tuple[Tuple[str, Callable[[Any], Any], Any], ...] = () OUT_KWARGS: Tuple[Tuple[str, Callable[[Any], Any], Any], ...] = () + @classmethod + def proto_name(cls) -> str: + ... + class In: def __init__(self, *args: Any, **kwargs: Any) -> None: ... diff --git a/loctrkd/rectifier.py b/loctrkd/rectifier.py index e4f29b2..47d9d05 100644 --- a/loctrkd/rectifier.py +++ b/loctrkd/rectifier.py @@ -6,6 +6,7 @@ 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 @@ -15,8 +16,30 @@ 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]: + ... + + 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?! @@ -50,7 +73,10 @@ def runserver(conf: ConfigParser) -> None: elif isinstance(rect, HintReport): try: lat, lon = qry.lookup( - rect.mcc, rect.mnc, rect.gsm_cells, rect.wifi_aps + rect.mcc, + rect.mnc, + rect.gsm_cells, + list((mac, strng) for _, mac, strng in rect.wifi_aps), ) log.debug( "Approximated lat=%s, lon=%s for %s", lat, lon, rect diff --git a/loctrkd/termconfig.py b/loctrkd/termconfig.py index 4968e28..14df8cf 100644 --- a/loctrkd/termconfig.py +++ b/loctrkd/termconfig.py @@ -49,9 +49,9 @@ def runserver(conf: ConfigParser) -> None: zsub = zctx.socket(zmq.SUB) # type: ignore zsub.connect(conf.get("collector", "publishurl")) for proto in ( - proto_name(STATUS), - proto_name(SETUP), - proto_name(POSITION_UPLOAD_INTERVAL), + STATUS.proto_name(), + SETUP.proto_name(), + POSITION_UPLOAD_INTERVAL.proto_name(), ): zsub.setsockopt(zmq.SUBSCRIBE, topic(proto)) zpush = zctx.socket(zmq.PUSH) # type: ignore diff --git a/loctrkd/zx303proto.py b/loctrkd/zx303proto.py index 2a0ede6..63dc3f5 100755 --- a/loctrkd/zx303proto.py +++ b/loctrkd/zx303proto.py @@ -44,12 +44,11 @@ __all__ = ( "proto_handled", "parse_message", "probe_buffer", - "proto_name", "DecodeError", "Respond", ) -PROTO_PREFIX = "ZX:" +PROTO_PREFIX: str = "ZX:" ### Deframer ### @@ -293,6 +292,11 @@ class GPS303Pkt(ProtoClass): # Overridden in subclasses, otherwise make empty payload return b"" + @classmethod + def proto_name(cls) -> str: + """Name of the command as used externally""" + return (PROTO_PREFIX + cls.__name__)[:16] + @property def packed(self) -> bytes: payload = self.encode() @@ -826,14 +830,8 @@ def proto_handled(proto: str) -> bool: return proto.startswith(PROTO_PREFIX) -def proto_name(obj: Union[Type[GPS303Pkt], GPS303Pkt]) -> str: - return PROTO_PREFIX + ( - obj.__class__.__name__ if isinstance(obj, GPS303Pkt) else obj.__name__ - ) - - def proto_of_message(packet: bytes) -> str: - return proto_name(CLASSES.get(packet[1], UNKNOWN)) + return CLASSES.get(packet[1], UNKNOWN).proto_name() def imei_from_packet(packet: bytes) -> Optional[str]: @@ -893,7 +891,7 @@ def parse_message(packet: bytes, is_incoming: bool = True) -> GPS303Pkt: def exposed_protos() -> List[Tuple[str, bool]]: return [ - (proto_name(cls)[:16], cls.RESPOND is Respond.EXT) + (cls.proto_name(), cls.RESPOND is Respond.EXT) for cls in CLASSES.values() if hasattr(cls, "rectified") ]