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:
parent
c01037d398
commit
fe1ebf2ec1
2
.github/workflows/master-build.yml
vendored
2
.github/workflows/master-build.yml
vendored
@ -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 }}
|
||||||
|
2
.github/workflows/python.yml
vendored
2
.github/workflows/python.yml
vendored
@ -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 }}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
2
tox.ini
2
tox.ini
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user