# Devices Context

## Overview

Identifies APRS equipment from packet data, maintaining a local registry of known devices.

## Schema: `Aprsme.Devices` (`lib/aprsme/devices.ex`)

Stores known APRS device information in the `devices` table:

| Field | Type | Notes |
|---|---|---|
| `identifier` | string | Unique device identifier |
| `class` | string | Device class (e.g., "tracker", "handheld") |
| `model` | string | Model name |
| `vendor` | string | Manufacturer name |
| `os` | string | Operating system |
| `contact` | string | Vendor/author contact |
| `features` | {:array, :string} | Feature tags |

No FK constraint: `device_identifier` on the `packets` table is a free-text string, not a DB-level reference.

## DeviceIdentification (`lib/aprsme/device_identification.ex`)

### Static Identification
Matches known MIC-E symbol patterns (regex-based) to identify ~20 common device types from packet data.

### Remote Registry
Fetches device database from `aprs-deviceid.aprsfoundation.org`:
- `maybe_refresh_devices/0` — Weekly refresh cycle
- `fetch_and_upsert_devices/0` — HTTP fetch wrapped in `CircuitBreaker`, upserts results into `devices` table
- `lookup_device_by_identifier/1` — Wildcard-matching lookup, delegates to `DeviceCache`

### Caching
- `DeviceCache` GenServer caches device data, refreshed daily
- Backed by `Aprsme.Cache` abstraction

## DeviceParser (`lib/aprsme/device_parser.ex`)

Extracts device identifiers from incoming packets by probing:
1. `data_extended.device_identifier` field
2. `destination` field
3. `data_extended.symbol_table_id` + `symbol_code` combination

Called during packet ingestion pipeline in `PacketConsumer`.

## Resilience

- `CircuitBreaker` wraps remote HTTP fetch, preventing cascading failures
- Cache ensures device lookups work even when remote source is unavailable
- Static patterns provide fallback identification without network calls
