add stored packet count

This commit is contained in:
Graham McIntire 2025-06-15 22:13:22 -05:00
parent 4afd6fb6b9
commit 94ef1e22b8
No known key found for this signature in database
5 changed files with 98 additions and 4 deletions

View file

@ -106,7 +106,8 @@ defmodule Aprs.Is do
uptime_seconds: 0,
login_id: Application.get_env(:aprs, :aprs_is_login_id, "W5ISP"),
filter: Application.get_env(:aprs, :aprs_is_default_filter, "r/33/-96/100"),
packet_stats: default_packet_stats()
packet_stats: default_packet_stats(),
stored_packet_count: Aprs.Packets.get_total_packet_count()
}
_pid ->
@ -126,7 +127,8 @@ defmodule Aprs.Is do
uptime_seconds: 0,
login_id: Application.get_env(:aprs, :aprs_is_login_id, "W5ISP"),
filter: Application.get_env(:aprs, :aprs_is_default_filter, "r/33/-96/100"),
packet_stats: default_packet_stats()
packet_stats: default_packet_stats(),
stored_packet_count: Aprs.Packets.get_total_packet_count()
}
end
end
@ -189,7 +191,8 @@ defmodule Aprs.Is do
uptime_seconds: DateTime.diff(DateTime.utc_now(), state.connected_at),
login_id: state.login_params.user_id,
filter: state.login_params.filter,
packet_stats: state.packet_stats
packet_stats: state.packet_stats,
stored_packet_count: Aprs.Packets.get_total_packet_count()
}
{:reply, status, state}

View file

@ -259,6 +259,13 @@ defmodule Aprs.Packets do
defp limit_results(query, _), do: query
@doc """
Gets the total count of stored packets in the database.
"""
def get_total_packet_count do
Repo.one(from p in Packet, select: count(p.id))
end
@doc """
Configure packet retention policy.

55
lib/aprs/passcode.ex Normal file
View file

@ -0,0 +1,55 @@
defmodule Aprs.Passcode do
@moduledoc """
Module for generating APRS passcodes from callsigns.
The passcode is a hash of the callsign used for authentication with APRS-IS servers.
"""
@doc """
Generates an APRS passcode for a given callsign.
## Parameters
- callsign: The amateur radio callsign (e.g., "W5ISP")
## Returns
- The generated passcode as an integer
## Examples
iex> Aprs.Passcode.generate("W5ISP")
12345
"""
def generate(callsign) when is_binary(callsign) do
# Split on '-' and take first part, uppercase, and limit to 10 chars
realcall =
callsign
|> String.split("-")
|> List.first()
|> String.upcase()
|> String.slice(0, 10)
# Convert string to charlist for easier processing
chars = String.to_charlist(realcall)
# Initial hash value
hash = 0x73E2
# Process characters in pairs
hash =
Enum.reduce_every(chars, 2, hash, fn [char1, char2], acc ->
acc
|> Bitwise.bxor(Bitwise.bsl(char1, 8))
|> Bitwise.bxor(char2)
end)
# Handle odd length callsigns
hash =
if rem(length(chars), 2) == 1 do
last_char = List.last(chars)
Bitwise.bxor(hash, Bitwise.bsl(last_char, 8))
else
hash
end
# Return final hash masked to 15 bits
Bitwise.band(hash, 0x7FFF)
end
end

View file

@ -172,7 +172,7 @@ defmodule AprsWeb.StatusLive.Index do
<!-- Packet Statistics -->
<div class="mt-4 pt-4 border-t border-gray-200">
<h3 class="text-sm font-medium text-gray-700 mb-3">Packet Statistics</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
<div class="flex items-center">
<span class="text-sm font-medium text-gray-500 mr-2">Total Packets:</span>
<span class="text-sm text-gray-900 font-mono">
@ -197,6 +197,13 @@ defmodule AprsWeb.StatusLive.Index do
<% end %>
</span>
</div>
<div class="flex items-center">
<span class="text-sm font-medium text-gray-500 mr-2">Stored Packets:</span>
<span class="text-sm text-gray-900 font-mono">
{format_number(@aprs_status.stored_packet_count)}
</span>
</div>
</div>
</div>

View file

@ -0,0 +1,22 @@
defmodule Aprs.PasscodeTest do
use ExUnit.Case
doctest Aprs.Passcode
describe "generate/1" do
test "generates correct passcode for W5ISP" do
assert Aprs.Passcode.generate("W5ISP") == 15748
end
test "handles callsigns with SSIDs" do
assert Aprs.Passcode.generate("W5ISP-1") == 15748
end
test "handles lowercase callsigns" do
assert Aprs.Passcode.generate("w5isp") == 15748
end
test "handles long callsigns" do
assert Aprs.Passcode.generate("W5ISP-LONG") == 15748
end
end
end