1
0
mirror of https://github.com/craigerl/aprsd.git synced 2025-07-31 12:52:24 -04:00

Test new packet serialization

This commit is contained in:
Hemna 2023-10-13 15:35:41 -04:00
parent c01037d398
commit fe1ebf2ec1
6 changed files with 73 additions and 22 deletions

View File

@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
python-version: ["3.9", "3.10", "3.11"] python-version: ["3.9", "3.10", "3.11", "3.12"]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}

View File

@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
python-version: ["3.9", "3.10", "3.11"] python-version: ["3.9", "3.10", "3.11", "3.12"]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}

View File

@ -1,7 +1,6 @@
import abc import abc
from dataclasses import asdict, dataclass, field from dataclasses import asdict, dataclass, field
import datetime from datetime import datetime
import json
import logging import logging
import re import re
import time import time
@ -9,9 +8,9 @@ import time
from typing import List from typing import List
import dacite import dacite
from dataclasses_json import dataclass_json
from aprsd.utils import counter from aprsd.utils import counter
from aprsd.utils import json as aprsd_json
LOG = logging.getLogger("APRSD") LOG = logging.getLogger("APRSD")
@ -28,12 +27,20 @@ PACKET_TYPE_BEACON = "beacon"
PACKET_TYPE_THIRDPARTY = "thirdparty" PACKET_TYPE_THIRDPARTY = "thirdparty"
PACKET_TYPE_UNCOMPRESSED = "uncompressed" PACKET_TYPE_UNCOMPRESSED = "uncompressed"
NO_DATE = datetime(1900, 10, 24)
def _init_timestamp(): def _init_timestamp():
"""Build a unix style timestamp integer""" """Build a unix style timestamp integer"""
return int(round(time.time())) return int(round(time.time()))
def _init_send_time():
# We have to use a datetime here, or the json encoder
# Fails on a NoneType.
return NO_DATE
def _init_msgNo(): # noqa: N802 def _init_msgNo(): # noqa: N802
"""For some reason __post__init doesn't get called. """For some reason __post__init doesn't get called.
@ -45,6 +52,32 @@ def _init_msgNo(): # noqa: N802
return c.value return c.value
def factory_from_dict(packet_dict):
pkt_type = get_packet_type(packet_dict)
# print(f"pkt_type {pkt_type}")
if pkt_type:
# if pkt_type == 'unknown':
# # try to determine it by the raw
# raw = packet_dict.get('raw')
# if raw:
# import aprslib
# type = get_packet_type(aprslib.parse(raw))
# print(f"raw type {type}")
cls = TYPE_LOOKUP[pkt_type]
# print(f"CLS {cls}")
return cls.from_dict(packet_dict)
def factory_from_json(packet_dict):
pkt_type = get_packet_type(packet_dict)
if pkt_type:
return TYPE_LOOKUP[pkt_type].from_json(packet_dict)
@dataclass_json
@dataclass(unsafe_hash=True) @dataclass(unsafe_hash=True)
class Packet(metaclass=abc.ABCMeta): class Packet(metaclass=abc.ABCMeta):
from_call: str = field(default=None) from_call: str = field(default=None)
@ -64,7 +97,17 @@ class Packet(metaclass=abc.ABCMeta):
# Fields related to sending packets out # Fields related to sending packets out
send_count: int = field(repr=False, default=0, compare=False, hash=False) send_count: int = field(repr=False, default=0, compare=False, hash=False)
retry_count: int = field(repr=False, default=3, compare=False, hash=False) retry_count: int = field(repr=False, default=3, compare=False, hash=False)
last_send_time: datetime.timedelta = field(repr=False, default=None, compare=False, hash=False) #last_send_time: datetime = field(
# metadata=dc_json_config(
# encoder=datetime.isoformat,
# decoder=datetime.fromisoformat,
# ),
# repr=True,
# default_factory=_init_send_time,
# compare=False,
# hash=False
#)
last_send_time: float = field(repr=False, default=0, compare=False, hash=False)
# Do we allow this packet to be saved to send later? # Do we allow this packet to be saved to send later?
allow_delay: bool = field(repr=False, default=True, compare=False, hash=False) allow_delay: bool = field(repr=False, default=True, compare=False, hash=False)
path: List[str] = field(default_factory=list, compare=False, hash=False) path: List[str] = field(default_factory=list, compare=False, hash=False)
@ -73,16 +116,13 @@ class Packet(metaclass=abc.ABCMeta):
def __post__init__(self): def __post__init__(self):
LOG.warning(f"POST INIT {self}") LOG.warning(f"POST INIT {self}")
@property
def __dict__(self):
return asdict(self)
@property @property
def json(self): def json(self):
""" """
get the json formated string get the json formated string
""" """
return json.dumps(self.__dict__, cls=aprsd_json.EnhancedJSONEncoder) #return json.dumps(self.__dict__, cls=aprsd_json.EnhancedJSONEncoder)
return self.to_json()
def get(self, key, default=None): def get(self, key, default=None):
"""Emulate a getter on a dict.""" """Emulate a getter on a dict."""
@ -288,7 +328,7 @@ class RejectPacket(Packet):
def _build_payload(self): def _build_payload(self):
self.payload = f":{self.to_call.ljust(9)} :rej{self.msgNo}" self.payload = f":{self.to_call.ljust(9)} :rej{self.msgNo}"
@dataclass_json
@dataclass(unsafe_hash=True) @dataclass(unsafe_hash=True)
class MessagePacket(Packet): class MessagePacket(Packet):
message_text: str = field(default=None) message_text: str = field(default=None)
@ -436,6 +476,13 @@ class GPSPacket(Packet):
) )
@dataclass
class StatusPacket(Packet):
status: str = None
messagecapable: bool = False
comment: str = None
@dataclass @dataclass
class MicEPacket(GPSPacket): class MicEPacket(GPSPacket):
messagecapable: bool = False messagecapable: bool = False
@ -567,7 +614,7 @@ class WeatherPacket(GPSPacket):
class ThirdParty(Packet): class ThirdParty(Packet):
# Holds the encapsulated packet # Holds the encapsulated packet
subpacket: Packet = None subpacket: Packet = field(default=None, compare=True, hash=False)
def __repr__(self): def __repr__(self):
"""Build the repr version of the packet.""" """Build the repr version of the packet."""
@ -600,7 +647,7 @@ def get_packet_type(packet: dict):
pkt_format = packet.get("format", None) pkt_format = packet.get("format", None)
msg_response = packet.get("response", None) msg_response = packet.get("response", None)
packet_type = "unknown" packet_type = PACKET_TYPE_UNKNOWN
if pkt_format == "message" and msg_response == "ack": if pkt_format == "message" and msg_response == "ack":
packet_type = PACKET_TYPE_ACK packet_type = PACKET_TYPE_ACK
elif pkt_format == "message" and msg_response == "rej": elif pkt_format == "message" and msg_response == "rej":
@ -620,6 +667,10 @@ def get_packet_type(packet: dict):
packet_type = PACKET_TYPE_WX packet_type = PACKET_TYPE_WX
elif pkt_format == PACKET_TYPE_THIRDPARTY: elif pkt_format == PACKET_TYPE_THIRDPARTY:
packet_type = PACKET_TYPE_THIRDPARTY packet_type = PACKET_TYPE_THIRDPARTY
if packet_type == PACKET_TYPE_UNKNOWN:
if "latitude" in packet:
packet_type = PACKET_TYPE_BEACON
return packet_type return packet_type

View File

@ -1,4 +1,3 @@
import datetime
import logging import logging
import time import time
@ -128,10 +127,10 @@ class SendPacketThread(aprsd_threads.APRSDThread):
# Message is still outstanding and needs to be acked. # Message is still outstanding and needs to be acked.
if packet.last_send_time: if packet.last_send_time:
# Message has a last send time tracking # Message has a last send time tracking
now = datetime.datetime.now() now = int(round(time.time()))
sleeptime = (packet.send_count + 1) * 31 sleeptime = (packet.send_count + 1) * 31
delta = now - packet.last_send_time delta = now - packet.last_send_time
if delta > datetime.timedelta(seconds=sleeptime): if delta > sleeptime:
# It's time to try to send it again # It's time to try to send it again
send_now = True send_now = True
else: else:
@ -140,7 +139,7 @@ class SendPacketThread(aprsd_threads.APRSDThread):
if send_now: if send_now:
# no attempt time, so lets send it, and start # no attempt time, so lets send it, and start
# tracking the time. # tracking the time.
packet.last_send_time = datetime.datetime.now() packet.last_send_time = int(round(time.time()))
send(packet, direct=True) send(packet, direct=True)
packet.send_count += 1 packet.send_count += 1
@ -173,13 +172,13 @@ class SendAckThread(aprsd_threads.APRSDThread):
if self.packet.last_send_time: if self.packet.last_send_time:
# Message has a last send time tracking # Message has a last send time tracking
now = datetime.datetime.now() now = int(round(time.time()))
# aprs duplicate detection is 30 secs? # aprs duplicate detection is 30 secs?
# (21 only sends first, 28 skips middle) # (21 only sends first, 28 skips middle)
sleep_time = 31 sleep_time = 31
delta = now - self.packet.last_send_time delta = now - self.packet.last_send_time
if delta > datetime.timedelta(seconds=sleep_time): if delta > sleep_time:
# It's time to try to send it again # It's time to try to send it again
send_now = True send_now = True
elif self.loop_count % 10 == 0: elif self.loop_count % 10 == 0:
@ -190,7 +189,7 @@ class SendAckThread(aprsd_threads.APRSDThread):
if send_now: if send_now:
send(self.packet, direct=True) send(self.packet, direct=True)
self.packet.send_count += 1 self.packet.send_count += 1
self.packet.last_send_time = datetime.datetime.now() self.packet.last_send_time = int(round(time.time()))
time.sleep(1) time.sleep(1)
self.loop_count += 1 self.loop_count += 1

View File

@ -4,6 +4,7 @@
# #
# pip-compile --annotation-style=line requirements.in # pip-compile --annotation-style=line requirements.in
# #
dataclasses-json
aprslib==0.7.2 aprslib==0.7.2
# via -r requirements.in # via -r requirements.in
attrs==23.1.0 attrs==23.1.0

View File

@ -2,7 +2,7 @@
minversion = 2.9.0 minversion = 2.9.0
skipdist = True skipdist = True
skip_missing_interpreters = true skip_missing_interpreters = true
envlist = pep8,py{39,310} envlist = pep8,py{39,310,311,312}
#requires = tox-pipenv #requires = tox-pipenv
# pip==22.0.4 # pip==22.0.4
# pip-tools==5.4.0 # pip-tools==5.4.0