from inspect import isclass
from struct import error, pack, unpack
from time import time
+from types import SimpleNamespace
from typing import (
Any,
Callable,
Union,
)
+from .common import CoordReport, HintReport, StatusReport
from .protomodule import ProtoClass
__all__ = (
"proto_handled",
"parse_message",
"probe_buffer",
- "proto_name",
"DecodeError",
"Respond",
- "GPS303Pkt",
- "UNKNOWN",
- "LOGIN",
- "SUPERVISION",
- "HEARTBEAT",
- "GPS_POSITIONING",
- "GPS_OFFLINE_POSITIONING",
- "STATUS",
- "HIBERNATION",
- "RESET",
- "WHITELIST_TOTAL",
- "WIFI_OFFLINE_POSITIONING",
- "TIME",
- "PROHIBIT_LBS",
- "GPS_LBS_SWITCH_TIMES",
- "REMOTE_MONITOR_PHONE",
- "SOS_PHONE",
- "DAD_PHONE",
- "MOM_PHONE",
- "STOP_UPLOAD",
- "GPS_OFF_PERIOD",
- "DND_PERIOD",
- "RESTART_SHUTDOWN",
- "DEVICE",
- "ALARM_CLOCK",
- "STOP_ALARM",
- "SETUP",
- "SYNCHRONOUS_WHITELIST",
- "RESTORE_PASSWORD",
- "WIFI_POSITIONING",
- "MANUAL_POSITIONING",
- "BATTERY_CHARGE",
- "CHARGER_CONNECTED",
- "CHARGER_DISCONNECTED",
- "VIBRATION_RECEIVED",
- "POSITION_UPLOAD_INTERVAL",
- "SOS_ALARM",
- "UNKNOWN_B3",
)
-PROTO_PREFIX = "ZX:"
+PROTO_PREFIX: str = "ZX:"
### Deframer ###
# 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()
ttup = (tup[0] % 100,) + tup[1:6]
return pack("BBBBBB", *ttup)
+ def rectified(self) -> CoordReport: # JSON-able dict
+ return CoordReport(
+ devtime=str(self.devtime),
+ battery_percentage=None,
+ accuracy=None,
+ altitude=None,
+ speed=self.speed,
+ direction=self.heading,
+ latitude=self.latitude,
+ longitude=self.longitude,
+ )
+
class GPS_POSITIONING(_GPS_POSITIONING):
PROTO = 0x10
def out_encode(self) -> bytes: # Set interval in minutes
return pack("B", self.upload_interval)
+ def rectified(self) -> StatusReport:
+ return StatusReport(battery_percentage=self.batt)
+
class HIBERNATION(GPS303Pkt): # Server can send to send devicee to sleep
PROTO = 0x14
]
)
+ def rectified(self) -> HintReport:
+ return HintReport(
+ devtime=str(self.devtime),
+ battery_percentage=None,
+ mcc=self.mcc,
+ mnc=self.mnc,
+ gsm_cells=self.gsm_cells,
+ wifi_aps=[("<UNKNOWN>", mac, sig) for mac, sig in self.wifi_aps],
+ )
+
class WIFI_OFFLINE_POSITIONING(_WIFI_POSITIONING):
PROTO = 0x17
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]:
def exposed_protos() -> List[Tuple[str, bool]]:
return [
- (proto_name(GPS_POSITIONING), True),
- (proto_name(WIFI_POSITIONING), False),
- (proto_name(STATUS), True),
+ (cls.proto_name(), cls.RESPOND is Respond.EXT)
+ for cls in CLASSES.values()
+ if hasattr(cls, "rectified")
]