deviceid

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 4, 2026 License: BSD-3-Clause Imports: 7 Imported by: 0

README

go-aprs-deviceid

APRS device identifier - Go edition

This is a Go port of the Ham::APRS::DeviceID Perl module. It identifies the manufacturer and model of an APRS transmitter by examining a parsed APRS packet (as provided by go-aprs-fap) and looking up the device in the tocalls.yaml identification database.

AI-assisted port

This Go module was created using the Claude Code AI agent, by letting it inspect the old Perl code. The original Perl module's identification logic has been retained in the Go implementation.

Identification methods

  • Tocall matching: exact and wildcard destination callsign patterns
  • Mic-E legacy devices: Kenwood TH-D7A, TH-D72, TH-D74, TM-D700, TM-D710 (identified by comment prefix/suffix)
  • Mic-E new-style suffix codes: Yaesu, Byonics, Anytone, and other devices using 2-character Mic-E device suffixes
  • Messaging capability: detected from Mic-E prefix character or device feature flags

Installation

go get github.com/hessu/go-aprs-deviceid

You will also need a copy of tocalls.yaml from the aprs-deviceid repository.

Usage

package main

import (
    "fmt"
    "github.com/hessu/go-aprs-fap"
    "github.com/hessu/go-aprs-deviceid"
)

func main() {
    // Open the device identification database
    db, err := deviceid.Open("tocalls.yaml")
    if err != nil {
        fmt.Printf("Error loading DB: %v\n", err)
        return
    }

    // Parse a packet
    raw := "N0CALL>APDR15,WIDE1-1:!6028.51N/02505.68E#PHG2360"
    p, err := fap.Parse(raw)
    if err != nil {
        fmt.Printf("Parse error: %v\n", err)
        return
    }

    // Identify the device
    did, comment, err := db.Identify(p)
    if err != nil {
        fmt.Printf("Unknown device: %v\n", err)
        return
    }

    fmt.Printf("Vendor: %s\n", did.Vendor)
    fmt.Printf("Model: %s\n", did.Model)
    fmt.Printf("Comment: %s\n", comment)
}

Hot-reloading

The DeviceDB is concurrency-safe. You can call Identify from multiple goroutines simultaneously. To pick up changes to the tocalls.yaml file without restarting, call CheckReload periodically from a single goroutine:

reloaded, err := db.CheckReload()
if err != nil {
    log.Printf("Reload error: %v", err)
} else if reloaded {
    log.Println("Database reloaded")
}

CheckReload compares the file's inode and mtime and only reparses when the file has actually changed. You can optionally pass a new path to switch to a different YAML file:

reloaded, err := db.CheckReload("/new/path/tocalls.yaml")

Device identification database

The tocalls.yaml database is maintained separately at https://github.com/aprsorg/aprs-deviceid and is available in YAML, JSON and XML formats for use in other applications and programming languages. It is licensed under the CC BY-SA 2.0 license.

See also

Copyright (C) 2026 Heikki Hannikainen

Available under the 3-clause BSD license, details in LICENSE.

Documentation

Overview

Package deviceid identifies APRS transmitter devices from parsed packets. It uses the community-maintained tocalls.yaml database to determine the vendor, model, and class of the transmitting device.

Index

Constants

This section is empty.

Variables

View Source
var ErrNoMatch = errors.New("no device match")

ErrNoMatch is returned when no device match is found for a packet.

Functions

This section is empty.

Types

type DeviceDB

type DeviceDB struct {
	// contains filtered or unexported fields
}

DeviceDB is a concurrency-safe device identification database that supports hot-reloading. Use Open to create one, then call Identify from any number of goroutines. Call CheckReload periodically to pick up changes to the underlying YAML file.

func Open

func Open(yamlPath string) (*DeviceDB, error)

Open loads a tocalls.yaml file and returns a DeviceDB ready for concurrent use. Call Identify to look up devices, and CheckReload to pick up file changes.

func (*DeviceDB) CheckReload

func (ddb *DeviceDB) CheckReload(path ...string) (bool, error)

CheckReload checks whether the database file has changed (by comparing inode and mtime) and reloads it if so. An optional path argument switches the database to a different YAML file. Returns true if the database was reloaded. It is safe to call from a single goroutine while other goroutines call Identify concurrently.

func (*DeviceDB) Identify

func (ddb *DeviceDB) Identify(p *fap.Packet) (*DeviceID, string, error)

Identify determines the device that transmitted the given packet. It is safe to call concurrently from multiple goroutines. Returns (deviceID, updatedComment, error). updatedComment has Mic-E device codes stripped from the comment. Returns nil DeviceID and ErrNoMatch if no match is found.

type DeviceID

type DeviceID struct {
	Vendor    string   // Manufacturer/author
	Model     string   // Device/software model
	Class     string   // Device class: wx, tracker, rig, ht, app, software, digi, dstar, satellite
	OS        string   // Operating system (optional)
	Features  []string // Feature flags: "messaging", "item-in-msg"
	Messaging bool     // Device supports APRS messaging
}

DeviceID holds the identified device information.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL