X-Git-Url: http://average.org/gitweb/?a=blobdiff_plain;f=gps303%2Fgps303proto.py;h=8036d65e92a1a2e789b16b68774817c7a303a13c;hb=af6691efc04cf2fb6aaa22be606b6468cceaffb6;hp=8f4ffcce124e23fd1a4baeb236e434578cbcae5f;hpb=5e1e7a4d37a1e149d5e899dada7b55a863cd8e64;p=loctrkd.git diff --git a/gps303/gps303proto.py b/gps303/gps303proto.py index 8f4ffcc..8036d65 100755 --- a/gps303/gps303proto.py +++ b/gps303/gps303proto.py @@ -17,13 +17,14 @@ Forewarnings: from datetime import datetime, timezone from enum import Enum from inspect import isclass -from struct import pack, unpack +from struct import error, pack, unpack __all__ = ( "class_by_prefix", "inline_response", "parse_message", "proto_by_name", + "DecodeError", "Respond", "GPS303Pkt", "UNKNOWN", @@ -66,6 +67,12 @@ __all__ = ( ) +class DecodeError(Exception): + def __init__(self, e, **kwargs): + super().__init__(e) + for k, v in kwargs.items(): + setattr(self, k, v) + def intx(x): if isinstance(x, str): x = int(x, 0) @@ -157,7 +164,10 @@ class GPS303Pkt(metaclass=MetaPkt): assert not args or (len(args) == 2 and not kwargs) if args: # guaranteed to be two arguments at this point self.length, self.payload = args - self.decode(self.length, self.payload) + try: + self.decode(self.length, self.payload) + except error as e: + raise DecodeError(e, obj=self) else: for kw, typ, dfl in self.KWARGS: setattr(self, kw, typ(kwargs.pop(kw, dfl))) @@ -297,7 +307,6 @@ class STATUS(GPS303Pkt): class HIBERNATION(GPS303Pkt): # Server can send to send devicee to sleep PROTO = 0x14 - RESPOND = Respond.INL class RESET(GPS303Pkt): @@ -657,12 +666,20 @@ def parse_message(packet, is_incoming=True): """From a packet (without framing bytes) derive the XXX.In object""" length, proto = unpack("BB", packet[:2]) payload = packet[2:] - if proto in CLASSES: - if is_incoming: - return CLASSES[proto].In(length, payload) - else: - return CLASSES[proto].Out(length, payload) + if proto not in CLASSES: + cause = ValueError(f"Proto {proto} is unknown") else: + try: + if is_incoming: + return CLASSES[proto].In(length, payload) + else: + return CLASSES[proto].Out(length, payload) + except DecodeError as e: + cause = e + if is_incoming: retobj = UNKNOWN.In(length, payload) - retobj.PROTO = proto # Override class attr with object attr - return retobj + else: + retobj = UNKNOWN.Out(length, payload) + retobj.PROTO = proto # Override class attr with object attr + retobj.cause = cause + return retobj