add more device ids
This commit is contained in:
parent
369ce05f1a
commit
5c171e6acb
6 changed files with 226 additions and 41 deletions
|
|
@ -13,13 +13,6 @@ config :aprs, AprsWeb.Endpoint, cache_static_manifest: "priv/static/cache_manife
|
|||
|
||||
# Runtime production configuration, including reading
|
||||
|
||||
# Do not print debug messages in production
|
||||
# of environment variables, is done on config/runtime.exs.
|
||||
config :logger, level: :info
|
||||
|
||||
# Configures Swoosh API Client
|
||||
config :swoosh, :api_client, Aprs.Finch
|
||||
|
||||
config :esbuild,
|
||||
version: "0.17.11",
|
||||
default: [
|
||||
|
|
@ -27,3 +20,10 @@ config :esbuild,
|
|||
cd: Path.expand("../assets", __DIR__),
|
||||
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
|
||||
]
|
||||
|
||||
# Do not print debug messages in production
|
||||
# of environment variables, is done on config/runtime.exs.
|
||||
config :logger, level: :info
|
||||
|
||||
# Configures Swoosh API Client
|
||||
config :swoosh, :api_client, Aprs.Finch
|
||||
|
|
|
|||
80
lib/aprs/device_identification.ex
Normal file
80
lib/aprs/device_identification.ex
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
defmodule Aprs.DeviceIdentification do
|
||||
@moduledoc """
|
||||
Handles APRS device identification based on the APRS device identification database.
|
||||
"""
|
||||
|
||||
@doc """
|
||||
Identifies the manufacturer and model of an APRS device based on its symbol pattern.
|
||||
Returns a tuple of {manufacturer, model} or "Unknown" if the device cannot be identified.
|
||||
"""
|
||||
@spec identify_device(String.t()) :: String.t()
|
||||
def identify_device(symbols) do
|
||||
case symbols do
|
||||
# Original MIC-E devices
|
||||
" " <> <<0, 0>> -> "Original MIC-E"
|
||||
# Kenwood devices
|
||||
">" <> <<0>> <> "^" -> "Kenwood TH-D74"
|
||||
">" <> <<0, 0>> -> "Kenwood TH-D74A"
|
||||
"]" <> <<0>> <> "=" -> "Kenwood DM-710"
|
||||
"]" <> <<0, 0>> -> "Kenwood DM-700"
|
||||
# Yaesu devices
|
||||
"`_" <> " " -> "Yaesu VX-8"
|
||||
"`_" <> "\"" -> "Yaesu FTM-350"
|
||||
"`_" <> "#" -> "Yaesu VX-8G"
|
||||
"`_" <> "$" -> "Yaesu FT1D"
|
||||
"`_" <> "%" -> "Yaesu FTM-400DR"
|
||||
"`_" <> ")" -> "Yaesu FTM-100D"
|
||||
"`_" <> "(" -> "Yaesu FT2D"
|
||||
# Other devices
|
||||
"` X" -> "AP510"
|
||||
"`" <> <<0, 0>> -> "Mic-Emsg"
|
||||
"'|3" -> "Byonics TinyTrack3"
|
||||
"'|4" -> "Byonics TinyTrack4"
|
||||
"':4" -> "SCS GmbH & Co. P4dragon DR-7400 modems"
|
||||
"':8" -> "SCS GmbH & Co. P4dragon DR-7800 modems"
|
||||
"'" <> <<0, 0>> -> "McTrackr"
|
||||
<<0>> <> "\"" <> <<0>> -> "Hamhud"
|
||||
<<0>> <> "/" <> <<0>> -> "Argent"
|
||||
<<0>> <> "^" <> <<0>> -> "HinzTec anyfrog"
|
||||
<<0>> <> "*" <> <<0>> -> "APOZxx www.KissOZ.dk Tracker. OZ1EKD and OZ7HVO"
|
||||
<<0>> <> "~" <> <<0>> -> "Other"
|
||||
# Unknown devices
|
||||
_ -> "Unknown"
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns a list of all known device manufacturers.
|
||||
"""
|
||||
@spec known_manufacturers() :: [String.t()]
|
||||
def known_manufacturers do
|
||||
[
|
||||
"Original MIC-E",
|
||||
"Kenwood",
|
||||
"Yaesu",
|
||||
"AP510",
|
||||
"Byonics",
|
||||
"SCS GmbH & Co.",
|
||||
"McTrackr",
|
||||
"Hamhud",
|
||||
"Argent",
|
||||
"HinzTec",
|
||||
"APOZxx",
|
||||
"Other"
|
||||
]
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns a list of all known device models for a given manufacturer.
|
||||
"""
|
||||
@spec known_models(String.t()) :: [String.t()]
|
||||
def known_models(manufacturer) do
|
||||
case manufacturer do
|
||||
"Kenwood" -> ["TH-D74", "TH-D74A", "DM-710", "DM-700"]
|
||||
"Yaesu" -> ["VX-8", "FTM-350", "VX-8G", "FT1D", "FTM-400DR", "FTM-100D", "FT2D"]
|
||||
"Byonics" -> ["TinyTrack3", "TinyTrack4"]
|
||||
"SCS GmbH & Co." -> ["P4dragon DR-7400 modems", "P4dragon DR-7800 modems"]
|
||||
_ -> []
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -9,8 +9,16 @@
|
|||
</.live_title>
|
||||
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
|
||||
<link phx-track-static rel="stylesheet" href={~p"/assets/vendor/leaflet/leaflet.css"} />
|
||||
<script defer phx-track-static type="text/javascript" src={~p"/assets/vendor/leaflet/leaflet.js"} data-source-map="false"></script>
|
||||
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}></script>
|
||||
<script
|
||||
defer
|
||||
phx-track-static
|
||||
type="text/javascript"
|
||||
src={~p"/assets/vendor/leaflet/leaflet.js"}
|
||||
data-source-map="false"
|
||||
>
|
||||
</script>
|
||||
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
|
||||
</script>
|
||||
</head>
|
||||
<body class={body_class(assigns)}>
|
||||
{@inner_content}
|
||||
|
|
|
|||
|
|
@ -644,31 +644,9 @@ defmodule Parser do
|
|||
end
|
||||
|
||||
@spec parse_manufacturer(binary()) :: String.t()
|
||||
def parse_manufacturer(<<" ", _::binary-size(2)>>), do: "Original MIC-E"
|
||||
def parse_manufacturer(<<">", _, "^">>), do: "Kenwood TH-D74"
|
||||
def parse_manufacturer(<<">", _::binary-size(2)>>), do: "Kenwood TH-D74A"
|
||||
def parse_manufacturer(<<"]", _, "=">>), do: "Kenwood DM-710"
|
||||
def parse_manufacturer(<<"]", _::binary-size(2)>>), do: "Kenwood DM-700"
|
||||
def parse_manufacturer(<<"`", "_", " ">>), do: "Yaesu VX-8"
|
||||
def parse_manufacturer(<<"`", "_", "\"">>), do: "Yaesu FTM-350"
|
||||
def parse_manufacturer(<<"`", "_", "#">>), do: "Yaesu VX-8G"
|
||||
def parse_manufacturer(<<"`", "_", "$">>), do: "Yaesu FT1D"
|
||||
def parse_manufacturer(<<"`", "_", "%">>), do: "Yaesu FTM-400DR"
|
||||
def parse_manufacturer(<<"`", "_", ")">>), do: "Yaesu FTM-100D"
|
||||
def parse_manufacturer(<<"`", "_", "(">>), do: "Yaesu FT2D"
|
||||
def parse_manufacturer(<<"`", " ", "X">>), do: "AP510"
|
||||
def parse_manufacturer(<<"`", _::binary-size(2)>>), do: "Mic-Emsg"
|
||||
def parse_manufacturer(<<"'", "|", "3">>), do: "Byonics TinyTrack3"
|
||||
def parse_manufacturer(<<"'", "|", "4">>), do: "Byonics TinyTrack4"
|
||||
def parse_manufacturer(<<"'", ":", "4">>), do: "SCS GmbH & Co. P4dragon DR-7400 modems"
|
||||
def parse_manufacturer(<<"'", ":", "8">>), do: "SCS GmbH & Co. P4dragon DR-7800 modems"
|
||||
def parse_manufacturer(<<"'", _::binary-size(2)>>), do: "McTrackr"
|
||||
def parse_manufacturer(<<_, "\"", _>>), do: "Hamhud ?"
|
||||
def parse_manufacturer(<<_, "/", _>>), do: "Argent ?"
|
||||
def parse_manufacturer(<<_, "^", _>>), do: "HinzTec anyfrog"
|
||||
def parse_manufacturer(<<_, "*", _>>), do: "APOZxx www.KissOZ.dk Tracker. OZ1EKD and OZ7HVO"
|
||||
def parse_manufacturer(<<_, "~", _>>), do: "Other"
|
||||
def parse_manufacturer(_), do: "Unknown"
|
||||
def parse_manufacturer(symbols) do
|
||||
Aprs.DeviceIdentification.identify_device(symbols)
|
||||
end
|
||||
|
||||
@spec find_matches(Regex.t(), String.t()) :: [String.t()]
|
||||
defp find_matches(regex, text) do
|
||||
|
|
|
|||
92
test/aprs/device_identification_test.exs
Normal file
92
test/aprs/device_identification_test.exs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
defmodule Aprs.DeviceIdentificationTest do
|
||||
use ExUnit.Case
|
||||
|
||||
alias Aprs.DeviceIdentification
|
||||
|
||||
describe "identify_device/1" do
|
||||
test "identifies Original MIC-E devices" do
|
||||
assert DeviceIdentification.identify_device(" " <> <<0, 0>>) == "Original MIC-E"
|
||||
end
|
||||
|
||||
test "identifies Kenwood devices" do
|
||||
assert DeviceIdentification.identify_device(">" <> <<0>> <> "^") == "Kenwood TH-D74"
|
||||
assert DeviceIdentification.identify_device(">" <> <<0, 0>>) == "Kenwood TH-D74A"
|
||||
assert DeviceIdentification.identify_device("]" <> <<0>> <> "=") == "Kenwood DM-710"
|
||||
assert DeviceIdentification.identify_device("]" <> <<0, 0>>) == "Kenwood DM-700"
|
||||
end
|
||||
|
||||
test "identifies Yaesu devices" do
|
||||
assert DeviceIdentification.identify_device("`_" <> " ") == "Yaesu VX-8"
|
||||
assert DeviceIdentification.identify_device("`_" <> "\"") == "Yaesu FTM-350"
|
||||
assert DeviceIdentification.identify_device("`_" <> "#") == "Yaesu VX-8G"
|
||||
assert DeviceIdentification.identify_device("`_" <> "$") == "Yaesu FT1D"
|
||||
assert DeviceIdentification.identify_device("`_" <> "%") == "Yaesu FTM-400DR"
|
||||
assert DeviceIdentification.identify_device("`_" <> ")") == "Yaesu FTM-100D"
|
||||
assert DeviceIdentification.identify_device("`_" <> "(") == "Yaesu FT2D"
|
||||
end
|
||||
|
||||
test "identifies other devices" do
|
||||
assert DeviceIdentification.identify_device("` X") == "AP510"
|
||||
assert DeviceIdentification.identify_device("`" <> <<0, 0>>) == "Mic-Emsg"
|
||||
assert DeviceIdentification.identify_device("'|3") == "Byonics TinyTrack3"
|
||||
assert DeviceIdentification.identify_device("'|4") == "Byonics TinyTrack4"
|
||||
|
||||
assert DeviceIdentification.identify_device("':4") ==
|
||||
"SCS GmbH & Co. P4dragon DR-7400 modems"
|
||||
|
||||
assert DeviceIdentification.identify_device("':8") ==
|
||||
"SCS GmbH & Co. P4dragon DR-7800 modems"
|
||||
|
||||
assert DeviceIdentification.identify_device("'" <> <<0, 0>>) == "McTrackr"
|
||||
assert DeviceIdentification.identify_device(<<0>> <> "\"" <> <<0>>) == "Hamhud"
|
||||
assert DeviceIdentification.identify_device(<<0>> <> "/" <> <<0>>) == "Argent"
|
||||
assert DeviceIdentification.identify_device(<<0>> <> "^" <> <<0>>) == "HinzTec anyfrog"
|
||||
|
||||
assert DeviceIdentification.identify_device(<<0>> <> "*" <> <<0>>) ==
|
||||
"APOZxx www.KissOZ.dk Tracker. OZ1EKD and OZ7HVO"
|
||||
|
||||
assert DeviceIdentification.identify_device(<<0>> <> "~" <> <<0>>) == "Other"
|
||||
end
|
||||
|
||||
test "returns Unknown for unidentified devices" do
|
||||
assert DeviceIdentification.identify_device(<<0, 0, 0>>) == "Unknown"
|
||||
end
|
||||
end
|
||||
|
||||
describe "known_manufacturers/0" do
|
||||
test "returns list of known manufacturers" do
|
||||
manufacturers = DeviceIdentification.known_manufacturers()
|
||||
assert is_list(manufacturers)
|
||||
assert "Kenwood" in manufacturers
|
||||
assert "Yaesu" in manufacturers
|
||||
assert "Byonics" in manufacturers
|
||||
end
|
||||
end
|
||||
|
||||
describe "known_models/1" do
|
||||
test "returns list of known models for Kenwood" do
|
||||
models = DeviceIdentification.known_models("Kenwood")
|
||||
assert is_list(models)
|
||||
assert "TH-D74" in models
|
||||
assert "TH-D74A" in models
|
||||
assert "DM-710" in models
|
||||
assert "DM-700" in models
|
||||
end
|
||||
|
||||
test "returns list of known models for Yaesu" do
|
||||
models = DeviceIdentification.known_models("Yaesu")
|
||||
assert is_list(models)
|
||||
assert "VX-8" in models
|
||||
assert "FTM-350" in models
|
||||
assert "VX-8G" in models
|
||||
assert "FT1D" in models
|
||||
assert "FTM-400DR" in models
|
||||
assert "FTM-100D" in models
|
||||
assert "FT2D" in models
|
||||
end
|
||||
|
||||
test "returns empty list for unknown manufacturer" do
|
||||
assert DeviceIdentification.known_models("Unknown") == []
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -297,16 +297,34 @@ defmodule Parser.ParserTest do
|
|||
|
||||
test "handles various timestamp errors" do
|
||||
# Invalid hour (>23)
|
||||
result = Parser.parse_position_with_timestamp(false, "252345z4903.50N/07201.75W>", :timestamped_position)
|
||||
result =
|
||||
Parser.parse_position_with_timestamp(
|
||||
false,
|
||||
"252345z4903.50N/07201.75W>",
|
||||
:timestamped_position
|
||||
)
|
||||
|
||||
assert result.data_type == :position
|
||||
assert result.time =~ "252345"
|
||||
|
||||
# Invalid minute (>59)
|
||||
result = Parser.parse_position_with_timestamp(false, "096045z4903.50N/07201.75W>", :timestamped_position)
|
||||
result =
|
||||
Parser.parse_position_with_timestamp(
|
||||
false,
|
||||
"096045z4903.50N/07201.75W>",
|
||||
:timestamped_position
|
||||
)
|
||||
|
||||
assert result.data_type == :position
|
||||
|
||||
# Invalid second (>59)
|
||||
result = Parser.parse_position_with_timestamp(false, "092361z4903.50N/07201.75W>", :timestamped_position)
|
||||
result =
|
||||
Parser.parse_position_with_timestamp(
|
||||
false,
|
||||
"092361z4903.50N/07201.75W>",
|
||||
:timestamped_position
|
||||
)
|
||||
|
||||
assert result.data_type == :position
|
||||
|
||||
# Wrong format/length
|
||||
|
|
@ -316,7 +334,13 @@ defmodule Parser.ParserTest do
|
|||
|
||||
test "handles MDHM timestamp format errors" do
|
||||
# Invalid MDHM format
|
||||
result = Parser.parse_position_with_timestamp(false, "9999999/4903.50N/07201.75W>", :timestamped_position)
|
||||
result =
|
||||
Parser.parse_position_with_timestamp(
|
||||
false,
|
||||
"9999999/4903.50N/07201.75W>",
|
||||
:timestamped_position
|
||||
)
|
||||
|
||||
assert result.data_type == :position
|
||||
end
|
||||
end
|
||||
|
|
@ -475,10 +499,13 @@ defmodule Parser.ParserTest do
|
|||
%{matcher: "':4", result: "SCS GmbH & Co. P4dragon DR-7400 modems"},
|
||||
%{matcher: "':8", result: "SCS GmbH & Co. P4dragon DR-7800 modems"},
|
||||
%{matcher: "'" <> <<0, 0>>, result: "McTrackr"},
|
||||
%{matcher: <<0>> <> "\"" <> <<0>>, result: "Hamhud ?"},
|
||||
%{matcher: <<0>> <> "/" <> <<0>>, result: "Argent ?"},
|
||||
%{matcher: <<0>> <> "\"" <> <<0>>, result: "Hamhud"},
|
||||
%{matcher: <<0>> <> "/" <> <<0>>, result: "Argent"},
|
||||
%{matcher: <<0>> <> "^" <> <<0>>, result: "HinzTec anyfrog"},
|
||||
%{matcher: <<0>> <> "*" <> <<0>>, result: "APOZxx www.KissOZ.dk Tracker. OZ1EKD and OZ7HVO"},
|
||||
%{
|
||||
matcher: <<0>> <> "*" <> <<0>>,
|
||||
result: "APOZxx www.KissOZ.dk Tracker. OZ1EKD and OZ7HVO"
|
||||
},
|
||||
%{matcher: <<0>> <> "~" <> <<0>>, result: "Other"},
|
||||
%{matcher: <<0, 0, 0>>, result: "Unknown"}
|
||||
],
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue