1
0
mirror of https://github.com/craigerl/aprsd.git synced 2026-03-30 19:55:44 -04:00

107 Commits

Author SHA1 Message Date
490ff41cdc feat: Add configurable stats_store_interval for stats file saves
Add stats_store_interval config option to control how frequently
the statsstore.json file is written to disk. Default remains 10
seconds for backward compatibility.

This allows reducing disk I/O in production deployments and
can help avoid potential file corruption issues when external
processes read the stats file.
2026-03-27 17:37:16 -04:00
314f4da180 fix: Restore max_delta after custom stale_timeout test
The singleton's max_delta was being modified by test_init_custom_stale_timeout
and not restored, causing test_is_stale_connection_false to fail because
it expected 2 minutes but got 60 seconds.
2026-03-27 10:18:07 -04:00
f6eb383caf fix: Update test to work with singleton pattern
The APRSISDriver uses @singleton decorator which transforms the class
into a function. The test was incorrectly trying to use __new__ which
doesn't work with decorated singletons. Instead, re-initialize the
existing instance after changing the config.
2026-03-27 10:13:55 -04:00
930339d4cf feat: Add configurable stale_timeout for APRS-IS connections
Add a new 'stale_timeout' configuration option to the aprs_network config
group that allows users to customize how long to wait before considering
an APRS-IS connection stale.

Problem:
The stale connection threshold was hardcoded to 2 minutes. In environments
with frequent network hiccups or when using certain APRS-IS servers that
may drop connections silently, 2 minutes can be too long to wait before
reconnecting, resulting in significant data loss.

Solution:
- Add 'stale_timeout' option to aprsd/conf/client.py with default of 120s
- Update APRSISDriver.__init__ to use the config value
- Maintain backward compatibility by defaulting to 120s if not configured
- Update tests to handle the new configuration option

Usage:
  [aprs_network]
  stale_timeout = 60  # Reconnect after 60 seconds without data

The default remains 120 seconds (2 minutes) for backward compatibility.
2026-03-27 10:05:44 -04:00
bf258e4bcf chore(tests): fix unused variable linter warning in test_stats.py 2026-03-24 13:22:37 -04:00
85ebf8a274 refactor(threads): migrate TX threads to Event-based timing
- PacketSendSchedulerThread: Add daemon=False, replace time.sleep with self.wait
- AckSendSchedulerThread: Add daemon=False, replace time.sleep with self.wait
- SendPacketThread: Replace time.sleep with self.wait, remove manual loop_count
- SendAckThread: Replace time.sleep with self.wait, remove manual loop_count
- BeaconSendThread: Set self.period=CONF.beacon_interval, remove counter-based
  conditional, replace time.sleep with self.wait, remove _loop_cnt tracking
- Update tests to use new Event-based API
2026-03-24 13:22:37 -04:00
bc9ce61e59 refactor(threads): migrate RX threads to Event-based timing
- APRSDRXThread: Replace time.sleep with self.wait for interruptible waits
- APRSDRXThread.stop(): Use _shutdown_event.set() instead of thread_stop
- APRSDRXThread: Error recovery waits check for shutdown signal
- APRSDFilterThread: Use queue timeout with self.period for interruptible wait
- Remove unused time import
- Update tests to use new Event-based API
2026-03-24 13:22:37 -04:00
343ec3e81c refactor(threads): migrate stats threads to Event-based timing 2026-03-24 13:22:37 -04:00
43ba69e352 feat(threads): add join_non_daemon() to APRSDThreadList
Allows graceful shutdown by waiting for non-daemon threads to complete
while allowing daemon threads to be terminated immediately.
2026-03-24 13:22:36 -04:00
b7a37322e1 refactor(threads): add daemon, period, Event-based shutdown to APRSDThread
- Add daemon=True class attribute (subclasses override to False)
- Add period=1 class attribute for wait interval
- Replace thread_stop boolean with _shutdown_event (threading.Event)
- Add wait() method for interruptible sleeps
- Update tests for new Event-based API

BREAKING: thread_stop boolean replaced with _shutdown_event.
Code checking thread.thread_stop directly must use thread._shutdown_event.is_set()
2026-03-24 13:22:36 -04:00
6ea9889369 make consumer call signature consistent. 2026-02-18 14:11:25 -05:00
2b7e42802b update the keepalive for kiss 2026-02-18 14:00:52 -05:00
202c689658 Replace insecure pickle serialization with JSON
SECURITY FIX: Replace pickle.load() with json.load() to eliminate
remote code execution vulnerability from malicious pickle files.

Changes:
- Update ObjectStoreMixin to use JSON instead of pickle
- Add PacketJSONDecoder to reconstruct Packet objects from JSON
- Change file extension from .p to .json
- Add warning when old pickle files detected
- Add OrderedDict restoration for PacketList
- Update all tests to work with JSON format

Users with existing pickle files must run:
  aprsd dev migrate-pickle

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 16:07:55 -05:00
c5ca4f11af Added new APRSDPushStatsThread
This allows an aprsd server instance to push it's to a remote
location.
2026-02-10 18:49:23 -05:00
c62d0545c6 linting fix for test_tx 2026-02-05 17:04:57 -05:00
2180a52a9f added some mocks to speed up tests 2026-01-25 13:04:47 -05:00
3bcd03a514 Fix client / driver inconsistencies from protocol
The client registry defined a protocol that all drivers had
to implement.  This patch ensures that all methods are
consistent in the protocol definition.
2026-01-23 09:18:35 -05:00
24bc86424e Added --output-json for aprsd sample-config
This adds the ability to output the sample config
as json for non-human processing.
2026-01-21 15:45:48 -05:00
f2bd594a89 Added owner_callsign
This adds a new option in the aprsd.conf [DEFAULT] section
that denotes who is the callsign that officially owns this APRSD
instance.  This will be used for sending the instance info to the
registry.  It's useful when the callsign used by the instance is
something useful on the APRS network, which isn't necessarily the
same as the person that owns it.
2026-01-18 23:54:43 -05:00
cc8d834e5c Remove the login callsign in aprs_network
It's been confusing for a while that when we configured aprsd,
we had to enter the callsign in the [DEFAULT] section and
the [aprs_network] section.

This patch removes the login from the aprs_network section.  aprsd
will now use the main callsign in the [DEFAULT] section as the callsign
to login to the aprsis network.
2026-01-18 21:21:09 -05:00
2a8b7002f2 Added new TX Scheduler and pool.
This patch adds a new Send Packet scheduler and Ack Packet send
scheduler.  This prevents us from creating a new thread for each
packet that we send.
2026-01-16 23:38:46 -05:00
ce9fc3757d updated tox.ini 2026-01-16 22:46:51 -05:00
274d5af0e9 Refactored RX thread to not parse packets
The Main RX Thread that runs the client.consumer() call used to
parse packets as soon as it got them.  This lead to an iffecient
strategy for listen and acquire packets as fast as possible.
The APRSDRXThread now gets the raw packet from the client and
shoves it on the packet_queue.  The other threads that are looking
for packets on the packet_queue will parse the raw packet with
aprslib.  This allows us to capture packets as quickly as we can,
and then process those packets in the secondary threads.
This prevents a bottleneck capturing packets.
2026-01-14 15:00:14 -05:00
0620e63e72 added more unit tests 2026-01-12 23:26:49 -05:00
6cbd6452d5 kiss consumer update
this patch updates the kiss consumer to call the callback with the frame
as arg[0] just like aprslib does.
2026-01-12 23:25:06 -05:00
26242f7d43 Added unit tests for log 2026-01-06 18:57:54 -05:00
1da92e52ef Added unit tests for packets.
Also did some code cleanup.
2026-01-05 17:00:03 -05:00
f9979fa3da remove py310 testing 2025-12-29 20:49:54 -05:00
9ac881c56c Update WatchList and NotifySeenPlugin
The watchList was updating the last seen during RX time.
This happens before the NotifySeenPlugin even sees the packet,
so the callsign is never 'old'.  this patch fixes that, so the
watch list works.
2025-12-12 12:39:10 -05:00
d0dfaa42e6 Added unit tests 2025-12-09 17:20:23 -05:00
c34a82108b fixed tox failures 2025-11-26 20:28:25 -05:00
961d3e946a Fixed unit tests 2025-10-11 20:23:44 -04:00
af0feaf9c8 Fixed some unit tests
Fixed unit tests related to the updated static method signatures
of the client and drivers.
2025-10-07 14:18:50 -04:00
1c39546bb9 Reworked the entire client and drivers
This patch includes a completely reworked client structure.
There is now only 1 client object, that loads the appropriate
drivers.  The drivers are fake, aprsis and tcpkiss.

The TCPKISS client was written from scratch to avoid using asyncio.
Asyncion is nothing but a pain in the ass.
2025-04-23 20:52:02 -04:00
ec1adf4182 fixed list-plugins
This patch fixes the list-plugins and list-extensions.
Pypi changed their search page to require javascript, which
breaks python scripts....
2025-01-03 17:16:26 -05:00
72d068c0b8 Changed to ruff
This patch changes to the ruff linter.  SO MUCH quicker.
Removed grey and mypy as well.
2024-12-20 22:00:54 -05:00
3bba8a19da Removed LocationPlugin from aprsd core
This eliminates the requirement for geopy library and all it's deps.

The new location for the LocationPlugin is here:

https://github.com/hemna/aprsd-location-plugin
2024-12-11 15:55:16 -05:00
0880a356e6 Remove email plugin
This patch removes the email plugin from APRSD core.  The new
home for email plugin is here:

http://github.com/hemna/aprsd-email-plugin.git
2024-12-11 15:55:15 -05:00
8f8887f0e4 Remove webchat as a built in command.
Webchat will now be an extension that can be installed.
the extension is here:
https://github.com/hemna/aprsd-webchat-extension

Install it from git or pypi.
2024-12-11 15:55:15 -05:00
f66b96288f Fixed issue with packet object and prepare()
If any part of the code had a packet object and called prepare()
on it, it would create a msgNo if it wasn't set.  Sometimes we
get packets on the wire/RF that don't have a msgNo, so adding one
locally is wrong.   We should ONLY create a msgNo on a packet that
is destined for transmission.

This patch ensures that even if prepare() is called, that only
packets that are created locally for TX get a msgNo unless it
already exists from RX'd packets.
2024-11-26 16:52:39 -05:00
c82e9ba597 Fixed broken unit tests
This patch fixes some broken unit tests with the aprsis client.
2024-11-21 09:01:49 -05:00
224686cac5 Added unit test for APRSISClient 2024-11-05 13:39:44 -05:00
ab2de86726 Added unit test for ClientFactory 2024-11-05 12:32:16 -05:00
f1d066b8a9 Added unit test for client base
This patch adds a unit test for the APRSClient base class.
2024-11-05 12:15:59 -05:00
b317d0eb63 Refactor client and drivers
this patch refactors the client, drivers and client factory
to use the same Protocol mechanism used by the stats collector
to construct the proper client to be used according to
the configuration
2024-05-23 11:38:27 -04:00
f92b2ee364 Got unit tests working again 2024-04-02 09:30:45 -04:00
a270c75263 Fixed pep8 errors and missing files 2024-04-02 09:30:45 -04:00
f400c6004e Fix for filtering curse words
This patch adds a fix for filtering out curse words.
This adds a flag to the regex to ignore case!
2024-03-23 18:02:01 -04:00
f53df24988 More packet cleanup and tests 2024-03-23 17:05:41 -04:00
e386e91f6e Eliminated need for from_aprslib_dict
This patch eliminates the need for a custom
static method on each Packetclass to convert an aprslib
raw decoded dictionary -> correct Packet class.

This now uses the built in dataclasses_json from_dict()
mixin with an override for both the WeatherPacket and
the ThirdPartyPacket.

This patch also adds the TelemetryPacket and adds some
missing members to a few of the classes from test runs
decoding all packets from APRS-IS -> Packet classes.

Also adds some verification for packets in test_packets
2024-03-20 21:46:43 -04:00