Skip to content

Commit

Permalink
Test new packet serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
hemna committed Oct 13, 2023
1 parent acf2b62 commit c3573fd
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/master-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand Down
75 changes: 63 additions & 12 deletions aprsd/packets/core.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import abc
from dataclasses import asdict, dataclass, field
import datetime
import json
from datetime import datetime
import logging
import re
import time
# Due to a failure in python 3.8
from typing import List

import dacite
from dataclasses_json import dataclass_json

from aprsd.utils import counter
from aprsd.utils import json as aprsd_json


LOG = logging.getLogger("APRSD")
Expand All @@ -28,12 +27,20 @@
PACKET_TYPE_THIRDPARTY = "thirdparty"
PACKET_TYPE_UNCOMPRESSED = "uncompressed"

NO_DATE = datetime(1900, 10, 24)


def _init_timestamp():
"""Build a unix style timestamp integer"""
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
"""For some reason __post__init doesn't get called.
Expand All @@ -45,6 +52,32 @@ def _init_msgNo(): # noqa: N802
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)
class Packet(metaclass=abc.ABCMeta):
from_call: str = field(default=None)
Expand All @@ -64,7 +97,17 @@ class Packet(metaclass=abc.ABCMeta):
# Fields related to sending packets out
send_count: int = field(repr=False, default=0, 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?
allow_delay: bool = field(repr=False, default=True, compare=False, hash=False)
path: List[str] = field(default_factory=list, compare=False, hash=False)
Expand All @@ -73,16 +116,13 @@ class Packet(metaclass=abc.ABCMeta):
def __post__init__(self):
LOG.warning(f"POST INIT {self}")

@property
def __dict__(self):
return asdict(self)

@property
def json(self):
"""
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):
"""Emulate a getter on a dict."""
Expand Down Expand Up @@ -288,7 +328,7 @@ def __post__init__(self):
def _build_payload(self):
self.payload = f":{self.to_call.ljust(9)} :rej{self.msgNo}"


@dataclass_json
@dataclass(unsafe_hash=True)
class MessagePacket(Packet):
message_text: str = field(default=None)
Expand Down Expand Up @@ -436,6 +476,13 @@ def _build_raw(self):
)


@dataclass
class StatusPacket(Packet):
status: str = None
messagecapable: bool = False
comment: str = None


@dataclass
class MicEPacket(GPSPacket):
messagecapable: bool = False
Expand Down Expand Up @@ -567,7 +614,7 @@ def _build_raw(self):

class ThirdParty(Packet):
# Holds the encapsulated packet
subpacket: Packet = None
subpacket: Packet = field(default=None, compare=True, hash=False)

def __repr__(self):
"""Build the repr version of the packet."""
Expand Down Expand Up @@ -600,7 +647,7 @@ def get_packet_type(packet: dict):

pkt_format = packet.get("format", None)
msg_response = packet.get("response", None)
packet_type = "unknown"
packet_type = PACKET_TYPE_UNKNOWN
if pkt_format == "message" and msg_response == "ack":
packet_type = PACKET_TYPE_ACK
elif pkt_format == "message" and msg_response == "rej":
Expand All @@ -620,6 +667,10 @@ def get_packet_type(packet: dict):
packet_type = PACKET_TYPE_WX
elif pkt_format == 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


Expand Down
13 changes: 6 additions & 7 deletions aprsd/threads/tx.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import datetime
import logging
import time

Expand Down Expand Up @@ -128,10 +127,10 @@ def loop(self):
# Message is still outstanding and needs to be acked.
if packet.last_send_time:
# Message has a last send time tracking
now = datetime.datetime.now()
now = int(round(time.time()))
sleeptime = (packet.send_count + 1) * 31
delta = now - packet.last_send_time
if delta > datetime.timedelta(seconds=sleeptime):
if delta > sleeptime:
# It's time to try to send it again
send_now = True
else:
Expand All @@ -140,7 +139,7 @@ def loop(self):
if send_now:
# no attempt time, so lets send it, and start
# tracking the time.
packet.last_send_time = datetime.datetime.now()
packet.last_send_time = int(round(time.time()))
send(packet, direct=True)
packet.send_count += 1

Expand Down Expand Up @@ -173,13 +172,13 @@ def loop(self):

if self.packet.last_send_time:
# Message has a last send time tracking
now = datetime.datetime.now()
now = int(round(time.time()))

# aprs duplicate detection is 30 secs?
# (21 only sends first, 28 skips middle)
sleep_time = 31
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
send_now = True
elif self.loop_count % 10 == 0:
Expand All @@ -190,7 +189,7 @@ def loop(self):
if send_now:
send(self.packet, direct=True)
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)
self.loop_count += 1
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#
# pip-compile --annotation-style=line requirements.in
#
dataclasses-json
aprslib==0.7.2
# via -r requirements.in
attrs==23.1.0
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
minversion = 2.9.0
skipdist = True
skip_missing_interpreters = true
envlist = pep8,py{39,310}
envlist = pep8,py{39,310,311,312}
#requires = tox-pipenv
# pip==22.0.4
# pip-tools==5.4.0
Expand Down

0 comments on commit c3573fd

Please sign in to comment.