htmlfile = /var/lib/gps303/index.html
[storage]
-dbfn = /var/lib/gps303/gps303.sqlite
+dbfn = /var/lib/gps303/trkloc.sqlite
[lookaside]
# "opencellid" and "googlemaps" can be here. Both require an access token,
...
@staticmethod
- def proto_of_message(packet: bytes) -> int:
+ def proto_of_message(packet: bytes) -> str:
...
@staticmethod
imei text,
peeraddr text not null,
is_incoming int not null default TRUE,
- proto int not null,
+ proto text not null,
packet blob
)"""
("peeraddr", None),
("when", 0.0),
("imei", None),
- ("proto", -1),
+ ("proto", "UNKNOWN"),
("packet", b""),
)
}
def fetch(
- imei: str, matchlist: List[Tuple[bool, int]], backlog: int
+ imei: str, matchlist: List[Tuple[bool, str]], backlog: int
) -> List[Tuple[bool, float, bytes]]:
# matchlist is a list of tuples (is_incoming, proto)
# returns a list of tuples (is_incoming, timestamp, packet)
c.execute(
"""select tstamp, packet from events
where proto in (?, ?)""",
- (WIFI_POSITIONING.PROTO, WIFI_OFFLINE_POSITIONING.PROTO),
+ (proto_name(WIFI_POSITIONING), proto_name(WIFI_OFFLINE_POSITIONING)),
)
init({"googlemaps": {"accesstoken": sys.argv[2]}})
count = 0
"parse_message",
"probe_buffer",
"proto_by_name",
+ "proto_name",
"DecodeError",
"Respond",
"GPS303Pkt",
"UNKNOWN_B3",
)
+PROTO_PREFIX = "ZX"
+
### Deframer ###
MAXBUFFER: int = 4096
return CLASSES[proto]
+def proto_name(obj: Union[MetaPkt, GPS303Pkt]) -> str:
+ return (
+ PROTO_PREFIX
+ + ":"
+ + (
+ obj.__class__.__name__
+ if isinstance(obj, GPS303Pkt)
+ else obj.__name__
+ )
+ ).ljust(16, "\0")[:16]
+
+
def proto_by_name(name: str) -> int:
return PROTOS.get(name, -1)
-def proto_of_message(packet: bytes) -> int:
- return packet[1]
+def proto_of_message(packet: bytes) -> str:
+ return proto_name(CLASSES.get(packet[1], UNKNOWN))
def imei_from_packet(packet: bytes) -> Optional[str]:
- if proto_of_message(packet) == LOGIN.PROTO:
+ if packet[1] == LOGIN.PROTO:
msg = parse_message(packet)
if isinstance(msg, LOGIN):
return msg.imei
def is_goodbye_packet(packet: bytes) -> bool:
- return proto_of_message(packet) == HIBERNATION.PROTO
+ return packet[1] == HIBERNATION.PROTO
def inline_response(packet: bytes) -> Optional[bytes]:
- proto = proto_of_message(packet)
+ proto = packet[1]
if proto in CLASSES:
cls = CLASSES[proto]
if cls.RESPOND is Respond.INL:
import zmq
from . import common
-from .gps303proto import parse_message, WIFI_POSITIONING
+from .gps303proto import parse_message, proto_name, WIFI_POSITIONING
from .zmsg import Bcast, Resp, topic
log = getLogger("gps303/lookaside")
zctx = zmq.Context() # type: ignore
zsub = zctx.socket(zmq.SUB) # type: ignore
zsub.connect(conf.get("collector", "publishurl"))
- zsub.setsockopt(zmq.SUBSCRIBE, topic(WIFI_POSITIONING.PROTO))
+ zsub.setsockopt(zmq.SUBSCRIBE, topic(proto_name(WIFI_POSITIONING)))
zpush = zctx.socket(zmq.PUSH) # type: ignore
zpush.connect(conf.get("collector", "listenurl"))
and ((is_incoming = false and proto = ?)
or (is_incoming = true and proto = ?))
order by tstamp""",
- (sys.argv[2], WIFI_POSITIONING.PROTO, GPS_POSITIONING.PROTO),
+ (sys.argv[2], proto_name(WIFI_POSITIONING), proto_name(GPS_POSITIONING)),
)
print(
c.execute(
"""select tstamp, packet from events
where proto in (?, ?)""",
- (WIFI_POSITIONING.PROTO, WIFI_OFFLINE_POSITIONING.PROTO),
+ (proto_name(WIFI_POSITIONING), proto_name(WIFI_OFFLINE_POSITIONING)),
)
init({"opencellid": {"dbfn": sys.argv[2]}})
for timestamp, packet in c:
zsub = zctx.socket(zmq.SUB) # type: ignore
zsub.connect(conf.get("collector", "publishurl"))
for proto in (
- STATUS.PROTO,
- SETUP.PROTO,
- POSITION_UPLOAD_INTERVAL.PROTO,
+ proto_name(STATUS),
+ proto_name(SETUP),
+ proto_name(POSITION_UPLOAD_INTERVAL),
):
zsub.setsockopt(zmq.SUBSCRIBE, topic(proto))
zpush = zctx.socket(zmq.PUSH) # type: ignore
STATUS,
WIFI_POSITIONING,
parse_message,
+ proto_name,
)
from .zmsg import Bcast, topic
result = []
for is_incoming, timestamp, packet in fetch(
imei,
- [(True, GPS_POSITIONING.PROTO), (False, WIFI_POSITIONING.PROTO)],
+ [
+ (True, proto_name(GPS_POSITIONING)),
+ (False, proto_name(WIFI_POSITIONING)),
+ ],
numback,
):
msg = parse_message(packet, is_incoming=is_incoming)
for imei in neededsubs - activesubs:
zsub.setsockopt(
zmq.SUBSCRIBE,
- topic(GPS_POSITIONING.PROTO, True, imei),
+ topic(proto_name(GPS_POSITIONING), True, imei),
)
zsub.setsockopt(
zmq.SUBSCRIBE,
- topic(WIFI_POSITIONING.PROTO, False, imei),
+ topic(proto_name(WIFI_POSITIONING), False, imei),
)
zsub.setsockopt(
zmq.SUBSCRIBE,
- topic(STATUS.PROTO, True, imei),
+ topic(proto_name(STATUS), True, imei),
)
for imei in activesubs - neededsubs:
zsub.setsockopt(
zmq.UNSUBSCRIBE,
- topic(GPS_POSITIONING.PROTO, True, imei),
+ topic(proto_name(GPS_POSITIONING), True, imei),
)
zsub.setsockopt(
zmq.UNSUBSCRIBE,
- topic(WIFI_POSITIONING.PROTO, False, imei),
+ topic(proto_name(WIFI_POSITIONING), False, imei),
)
zsub.setsockopt(
zmq.UNSUBSCRIBE,
- topic(STATUS.PROTO, True, imei),
+ topic(proto_name(STATUS), True, imei),
)
activesubs = neededsubs
log.debug("Subscribed to: %s", activesubs)
__all__ = "Bcast", "Resp", "topic"
-def pack_peer(
+def pack_peer( # 18 bytes
peeraddr: Union[None, Tuple[str, int], Tuple[str, int, Any, Any]]
) -> bytes:
if peeraddr is None:
def topic(
- proto: int, is_incoming: bool = True, imei: Optional[str] = None
+ proto: str, is_incoming: bool = True, imei: Optional[str] = None
) -> bytes:
- return pack("BB", is_incoming, proto) + (
+ return pack("B16s", is_incoming, proto.encode()) + (
b"" if imei is None else pack("16s", imei.encode())
)
KWARGS = (
("is_incoming", True),
- ("proto", 256),
+ ("proto", "UNKNOWN"),
("imei", None),
("when", None),
("peeraddr", None),
def packed(self) -> bytes:
return (
pack(
- "BB16s",
+ "!B16s16sd",
int(self.is_incoming),
- self.proto,
+ self.proto[:16].ljust(16, "\0").encode(),
b"0000000000000000"
if self.imei is None
else self.imei.encode(),
- )
- + (
- b"\0\0\0\0\0\0\0\0"
- if self.when is None
- else pack("!d", self.when)
+ 0 if self.when is None else self.when,
)
+ pack_peer(self.peeraddr)
+ self.packet
)
def decode(self, buffer: bytes) -> None:
- self.is_incoming = bool(buffer[0])
- self.proto = buffer[1]
- self.imei: Optional[str] = buffer[2:18].decode()
- if self.imei == "0000000000000000":
- self.imei = None
- self.when = unpack("!d", buffer[18:26])[0]
- self.peeraddr = unpack_peer(buffer[26:44])
- self.packet = buffer[44:]
+ is_incoming, proto, imei, when = unpack("!B16s16sd", buffer[:41])
+ self.is_incoming = bool(is_incoming)
+ self.proto = proto.decode()
+ self.imei = (
+ None if imei == b"0000000000000000" else imei.decode().strip("\0")
+ )
+ self.when = when
+ self.peeraddr = unpack_peer(buffer[41:59])
+ self.packet = buffer[59:]
class Resp(_Zmsg):
def packed(self) -> bytes:
return (
pack(
- "16s",
+ "!16sd",
"0000000000000000"
if self.imei is None
else self.imei.encode(),
- )
- + (
- b"\0\0\0\0\0\0\0\0"
- if self.when is None
- else pack("!d", self.when)
+ 0 if self.when is None else self.when,
)
+ self.packet
)
def decode(self, buffer: bytes) -> None:
- self.imei = buffer[:16].decode()
- self.when = unpack("!d", buffer[16:24])[0]
+ imei, when = unpack("!16sd", buffer[:24])
+ self.imei = (
+ None if imei == b"0000000000000000" else imei.decode().strip("\0")
+ )
+
+ self.when = when
self.packet = buffer[24:]