Documentation
¶
Index ¶
- func Discover() string
- func DiscoverWith(opts DiscoverOptions) (string, error)
- type APIAuthConfig
- type APICORSConfig
- type APIConfig
- type AudioConfig
- type CCHuntConfig
- type Config
- type ConvChannelConfig
- type ConvToneConfig
- type DeviceConfig
- type DiscoverOptions
- type EqualizerConfig
- type LogConfig
- type MetricsConfig
- type Patch
- type RecordingsConfig
- type RetentionConfig
- type SDRConfig
- type ScannerConfig
- type StorageConfig
- type SystemConfig
- type ToneOutConfig
- type ToneProfileConfig
- type ToneProfileToneConfig
- type TrunkingConfig
- type Writer
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Discover ¶ added in v0.1.5
func Discover() string
Discover finds the daemon's config file using the standard precedence and returns it (or "" when none exists). Equivalent to DiscoverWith(DiscoverOptions{}): when multiple files share a directory, the first lexical match wins. Callers that want to prompt the operator should use DiscoverWith.
func DiscoverWith ¶ added in v0.1.5
func DiscoverWith(opts DiscoverOptions) (string, error)
DiscoverWith walks the standard precedence and returns the resolved config path (or "" when none exists). Steps:
- $GOPHERTRUNK_CONFIG — used verbatim, no existence check (an operator who sets the var should see a clear Load error if the file is missing, not a silent fallback to a different config).
- The first candidate directory containing one or more *.yaml / *.yml files. Within that directory: - 1 file → use it. - 2+ files → call opts.Pick; if nil, take the first.
Candidate directories (in order):
- <os.UserConfigDir()>/GopherTrunk (%APPDATA%\GopherTrunk on Windows, ~/.config/GopherTrunk on Linux, ~/Library/Application Support/GopherTrunk on macOS).
- <UserHomeDir>/Documents/GopherTrunk (the Windows installer's default — operators who accept it get auto-discovery without setting any env var).
- the current working directory.
Pick returning an error aborts discovery; the caller should surface the error rather than fall back to a default.
Types ¶
type APIAuthConfig ¶
type APIAuthConfig struct {
// Mode picks the auth policy. Recognised values:
// "" / "auto" → auto (the default — require a token on
// non-loopback binds, bypass on loopback)
// "required" / "on" → require a token on every mutation
// "disabled" / "off" → no auth, mutations wide open (the
// legacy `allow_mutations: true` behaviour)
Mode string `yaml:"mode"`
// Token is the inline bearer token (compared via crypto/subtle).
// Prefer TokenFile so the token doesn't live in config.yaml.
Token string `yaml:"token"`
// TokenFile is a path to a file containing the bearer token
// (whitespace stripped). The daemon re-reads it on every
// request so operators can rotate without a restart.
TokenFile string `yaml:"token_file"`
// TrustedNetworks is a list of CIDRs whose source addresses
// bypass the token check under `auto` mode. Loopback
// (127.0.0.1/32 and ::1/128) is implicitly trusted under
// `auto` and does not need to be listed here.
TrustedNetworks []string `yaml:"trusted_networks"`
}
APIAuthConfig configures bearer-token authentication on the HTTP API's mutation endpoints. See internal/api/AuthMode for the policy modes.
type APICORSConfig ¶ added in v0.1.3
type APICORSConfig struct {
// AllowedOrigins is the exact origin string the daemon
// echoes back in Access-Control-Allow-Origin. Browsers send
// the literal "null" for file:// loads. Use "*" to allow
// any origin (must not be combined with credentials).
AllowedOrigins []string `yaml:"allowed_origins"`
}
APICORSConfig configures cross-origin browser access to the HTTP API + WebSocket upgrade. Off by default; the daemon emits no Access-Control-* headers and rejects WS upgrades whose Origin header is not in AllowedOrigins.
Common values:
["null"] allow web UI opened via file:// ["http://laptop.local:8000"] allow a specific static host ["*"] allow any origin (use with auth)
type APIConfig ¶
type APIConfig struct {
HTTPAddr string `yaml:"http_addr"`
GRPCAddr string `yaml:"grpc_addr"`
AllowMutations bool `yaml:"allow_mutations"`
Auth APIAuthConfig `yaml:"auth"`
// CORS gates cross-origin browser requests. Off by default
// (no Access-Control-* headers emitted). Enable when serving
// the bundled web UI from a different origin than the daemon
// (e.g. opening web/index.html via file:// → Origin: null, or
// hosting the SPA on a separate static server).
CORS APICORSConfig `yaml:"cors"`
// TLSCert / TLSKey, when both set, switch both the HTTP and
// gRPC servers to TLS. Paths point at PEM-encoded files on
// disk that the daemon reads at start-up (rotation requires a
// restart). Leave both empty for plain TCP (the default;
// appropriate for loopback / private-network deployments).
// See docs/hardening.md §"Transport encryption (TLS)".
TLSCert string `yaml:"tls_cert"`
TLSKey string `yaml:"tls_key"`
}
APIConfig controls the HTTP REST + SSE + WebSocket and gRPC servers. Both addresses are TCP listen specifiers (":8080", "127.0.0.1:9000", etc.). An empty value disables that surface.
Auth gates the write endpoints (end call, set talkgroup priority/lockout, retention sweep, tone-detector reset, scanner cockpit, audio cockpit). See APIAuthConfig for the policy modes; the default `auto` mode bypasses auth on loopback binds and requires a bearer token on public binds.
AllowMutations is the legacy gate. Setting it to true logs a deprecation warning and maps to `auth.mode: disabled` so the daemon's existing wide-open behaviour is preserved.
type AudioConfig ¶
type AudioConfig struct {
// Enabled gates live playback. Default false. The recorder
// path is unaffected: WAVs land on disk whether audio is on
// or off.
Enabled bool `yaml:"enabled"`
// Device is the backend-specific output device name. Empty
// (or "default") routes to the system default sink. "null"
// forces the no-op backend even when Enabled=true.
Device string `yaml:"device"`
// SampleRate is the host playback rate in Hz. Default 8000;
// must match recordings.sample_rate so the composer's PCM
// frames don't need a resample stage.
SampleRate uint32 `yaml:"sample_rate"`
// BufferMs is the depth of the playback queue. Default 80.
BufferMs int `yaml:"buffer_ms"`
// Volume is the initial software gain (0..1). Default 0.8.
Volume float32 `yaml:"volume"`
// Muted is the initial mute state. Default false.
Muted bool `yaml:"muted"`
}
AudioConfig controls live audio playback to the host's speakers. The daemon mixes decoded PCM from the per-call composer and the conventional scanner into a single output stream, applied with software gain so volume / mute changes are instant.
Disabled by default — headless servers stay silent unless audio.enabled is set true. Backend init failure (e.g. no audio device, no PulseAudio / ALSA on the host) falls back to the null player automatically.
type CCHuntConfig ¶
type CCHuntConfig struct {
// Enabled defaults to true when any trunked system is configured.
// Set explicitly to false to ship without the hunter.
Enabled bool `yaml:"enabled"`
// DwellMs is the per-frequency wait window before declaring no
// lock. Defaults to 3000.
DwellMs int `yaml:"dwell_ms"`
// BackoffMs is the initial sleep after exhausting a system's CC
// list. Defaults to 5000. Doubles per failure up to MaxBackoffMs.
BackoffMs int `yaml:"backoff_ms"`
// MaxBackoffMs caps the exponential backoff. Defaults to 60000.
MaxBackoffMs int `yaml:"max_backoff_ms"`
}
CCHuntConfig tunes the hunter's dwell + exponential backoff.
type Config ¶
type Config struct {
Log LogConfig `yaml:"log"`
SDR SDRConfig `yaml:"sdr"`
Trunking TrunkingConfig `yaml:"trunking"`
API APIConfig `yaml:"api"`
Storage StorageConfig `yaml:"storage"`
Recordings RecordingsConfig `yaml:"recordings"`
Metrics MetricsConfig `yaml:"metrics"`
Retention RetentionConfig `yaml:"retention"`
ToneOut ToneOutConfig `yaml:"tone_out"`
Scanner ScannerConfig `yaml:"scanner"`
Audio AudioConfig `yaml:"audio"`
}
type ConvChannelConfig ¶
type ConvChannelConfig struct {
Label string `yaml:"label"`
FrequencyHz uint32 `yaml:"frequency_hz"`
Mode string `yaml:"mode"` // "fm" | "nfm"
SquelchDbFS float64 `yaml:"squelch_dbfs"` // default -50
HangtimeMs int `yaml:"hangtime_ms"` // default 1500
Priority int `yaml:"priority"` // 1..10, 0 = unset
// Tone is the optional CTCSS / DCS sub-audible squelch gate.
// Zero / "none" disables tone gating (default).
Tone ConvToneConfig `yaml:"tone"`
}
ConvChannelConfig is one entry in the conventional scan list.
type ConvToneConfig ¶
type ConvToneConfig struct {
// Mode is "ctcss", "dcs", or "" / "none".
Mode string `yaml:"mode"`
// CTCSSHz is the target CTCSS frequency (50..300 Hz).
// Required when Mode is "ctcss".
CTCSSHz float64 `yaml:"ctcss_hz"`
// DCSCode is the 3-digit octal DCS code. Required when
// Mode is "dcs". Detector wiring is a tracked follow-up; the
// config is accepted now so deployments can pre-stage YAML.
DCSCode string `yaml:"dcs_code"`
}
ConvToneConfig configures CTCSS / DCS gating for one conventional channel.
type DeviceConfig ¶
type DeviceConfig struct {
Serial string `yaml:"serial"`
Role string `yaml:"role"`
PPM int `yaml:"ppm"`
// Gain is the tuner gain setting. "auto" (or empty) selects
// the dongle's automatic gain control; any other value is
// parsed as a tenths-of-dB integer matching librtlsdr's
// gain table (e.g. "496" → 49.6 dB). Use `gophertrunk sdr
// list` to see the supported values per device.
Gain string `yaml:"gain"`
// BiasTee enables the dongle's 5V bias-tee output, used to
// power external LNAs through the antenna SMA. Off by
// default. Most modern RTL-SDR clones (e.g. NooElec NESDR
// Smart v5) wire this through; older units may toggle a
// GPIO bit that goes nowhere — librtlsdr accepts the call
// either way.
BiasTee bool `yaml:"bias_tee"`
}
type DiscoverOptions ¶ added in v0.1.5
DiscoverOptions tunes DiscoverWith. Pick is invoked when the chosen candidate directory contains more than one config file so the caller (typically the CLI) can prompt the operator. Pick always receives at least two paths; when nil, the first lexical match wins silently.
type EqualizerConfig ¶
type EqualizerConfig struct {
Enabled bool `yaml:"enabled"`
Taps int `yaml:"taps"` // default 8 when enabled
StepSize float32 `yaml:"step_size"` // default 1e-4 when enabled
}
EqualizerConfig is the YAML shape of the optional CMA equalizer in the per-call FM voice chain.
type MetricsConfig ¶
type MetricsConfig struct {
Enabled bool `yaml:"enabled"`
}
MetricsConfig toggles the Prometheus collector. The /metrics endpoint is mounted on the API HTTP server when both Enabled is true and the API HTTP address is configured.
type Patch ¶ added in v0.1.5
type Patch struct {
// Log.
LogLevel *string
LogFormat *string
// API.
APIHTTPAddr *string
APIGRPCAddr *string
APIAuthMode *string
// Audio.
AudioEnabled *bool
AudioDevice *string
AudioVolume *float32
AudioMuted *bool
AudioBufferMs *int
// Recordings.
RecordingsDir *string
RecordingsSampleRate *uint32
RecordingsWriteRaw *bool
// Retention.
RetentionCallLogDays *int
RetentionFilesDays *int
RetentionInterval *string
// SDR (sample rate only; device list edits go through a separate
// future endpoint because they're keyed by serial).
SDRSampleRate *uint32
// Scanner.
ScannerScanMode *string
ScannerManualTuneEnabled *bool
ScannerCCHuntEnabled *bool
ScannerCCHuntDwellMs *int
ScannerCCHuntBackoffMs *int
ScannerCCHuntMaxBackoff *int
// Storage.
StoragePath *string
StorageCCCacheFile *string
// Metrics.
MetricsEnabled *bool
}
Patch is a sparse Config — every field is a pointer so callers can say "leave alone" with nil. The settings PATCH endpoint and the SIGHUP reload path both pipe operator edits through this shape.
Only fields the daemon knows how to surface in the TUI / web UI settings panels are listed here; expand the struct as new editable knobs become available.
type RecordingsConfig ¶
type RecordingsConfig struct {
Dir string `yaml:"dir"`
SampleRate uint32 `yaml:"sample_rate"`
WriteRaw bool `yaml:"write_raw"`
// Equalizer enables the per-call CMA blind equalizer that the FM
// composer chain runs between the front-end LPF and the FM demod.
// Off by default; useful when receiving simulcast systems with
// multiple transmitters at slightly different arrival delays.
Equalizer EqualizerConfig `yaml:"equalizer"`
}
RecordingsConfig configures the per-call WAV recorder.
type RetentionConfig ¶
type RetentionConfig struct {
CallLogDays int `yaml:"call_log_days"`
FilesDays int `yaml:"files_days"`
Interval string `yaml:"interval"` // Go duration string; default 1h
}
RetentionConfig configures the background sweeper that ages out call log rows and recorded files. Zero values disable the corresponding sweep; both can be active independently.
type SDRConfig ¶
type SDRConfig struct {
SampleRate uint32 `yaml:"sample_rate"`
Devices []DeviceConfig `yaml:"devices"`
}
type ScannerConfig ¶
type ScannerConfig struct {
// ScanMode is "all" (every non-locked-out grant is followed,
// the original behavior) or "list" (only TGs with Scan=true).
// Empty string defaults to "all". Operators can flip this at
// runtime from the TUI via PATCH /api/v1/scanner.
ScanMode string `yaml:"scan_mode"`
// CCHunt configures the multi-system control-channel hunter.
CCHunt CCHuntConfig `yaml:"cc_hunt"`
// Conventional is the fixed-frequency analog scan list.
Conventional []ConvChannelConfig `yaml:"conventional"`
// ManualTuneEnabled forces construction of the conventional
// scanner so the TUI's `f` key (or POST
// /api/v1/scanner/manual_tune) can VFO-tune at runtime even
// when no static channels are configured. With this set the
// scanner steals one Voice SDR from the trunking pool
// regardless of how many Voice SDRs are available.
//
// Default false; the daemon auto-detects when at least two
// Voice SDRs are present (sum >= 2) and constructs the
// scanner from the spare without requiring this flag. To
// keep all Voice SDRs reserved for trunking even with a
// spare, leave this false and the auto-detect rule still
// holds — set ManualTuneDisabled to opt out entirely.
ManualTuneEnabled bool `yaml:"manual_tune_enabled"`
// ManualTuneDisabled vetoes the auto-detect rule. When true,
// the conventional scanner is constructed only when
// `conventional` channels are explicitly listed or
// ManualTuneEnabled is set true.
ManualTuneDisabled bool `yaml:"manual_tune_disabled"`
}
ScannerConfig controls the police-scanner subsystems: the CC hunter, the talkgroup scan-list mode, and the conventional FM scanner. Empty == defaults; the daemon stays backwards compatible with pre-scanner configs.
type StorageConfig ¶
type StorageConfig struct {
Path string `yaml:"path"`
// CCCacheFile is the JSON cache used by the CC hunter. Empty disables.
CCCacheFile string `yaml:"cc_cache_file"`
}
StorageConfig configures the SQLite call log. An empty Path disables persistence (the daemon still runs, just without a call history).
type SystemConfig ¶
type SystemConfig struct {
Name string `yaml:"name"`
Protocol string `yaml:"protocol"`
ControlChannels []uint32 `yaml:"control_channels"`
TalkgroupFile string `yaml:"talkgroup_file"`
// TETRAColourCode is the 30-bit extended colour code the TETRA
// scrambler uses to seed its LFSR (ETSI EN 300 392-2 §8.2.5).
// Set this to the per-cell colour code of the TETRA TMO system
// being decoded so the descrambler can recover the type-3
// stream. Bits 30..31 are silently ignored. Zero is valid only
// for BSCH (§8.2.5.2); non-BSCH channels need the per-cell
// colour code or descrambling produces garbage. Ignored for
// non-TETRA protocols.
TETRAColourCode uint32 `yaml:"tetra_colour_code"`
// TETRAChannel selects which TETRA logical channel lives in
// each burst window under ChannelCodingOn. Recognised values:
// "sch/hd" | "sch/f" | "sch/hu" | "bsch" | "aach". Empty
// defaults to "sch/hd" — the standard signaling channel for
// cc.locked / Grant events. Ignored for non-TETRA protocols.
TETRAChannel string `yaml:"tetra_channel"`
// TETRAChannelCoding gates the full ETSI EN 300 392-2 §8.3.1
// channel-coding chain (descramble + deinterleave + depuncture
// + Viterbi + CRC-16 verify + tail strip). Recognised values:
// "" / "on" / "true" / "1" (the new default — full chain;
// required for live on-air captures) or "off" / "false" / "0"
// (legacy raw-dibit path, opt-out for operators feeding pre-
// stripped DSD-FME / OP25 fixtures). Ignored for non-TETRA
// protocols.
TETRAChannelCoding string `yaml:"tetra_channel_coding"`
// LTRFCSMode enables the CRC-7 FCS check on the LTR Status
// Ingest path. Recognised values: "" / "on" / "true" / "1"
// (the new default — drop Status words whose FCS trailer
// doesn't match) or "off" / "false" / "0" (no verification —
// opt-out for synthesized fixtures whose FCS trailer isn't
// populated). Ignored for non-LTR protocols.
LTRFCSMode string `yaml:"ltr_fcs_mode"`
// LTRManchesterMode controls Manchester decoding of the
// sub-audible LTR bit stream. Recognised values: "" / "on" /
// "soft" (the new default — majority-decode + tolerate noise
// bursts; matches the dominant on-air encoding), "strict"
// (require a mid-bit transition per pair, drop transition-less
// pairs), "off" / "nrz" (raw NRZ — opt-out for synthesized NRZ
// fixtures). Ignored for non-LTR protocols.
LTRManchesterMode string `yaml:"ltr_manchester_mode"`
// P25Phase2TrellisMode enables the 4-state ½-rate trellis FEC
// decoder on the P25 Phase 2 MAC PDU window. Recognised values:
// "" / "on" / "true" / "1" (the new default — 146 channel
// dibits via the TIA-102.AABF trellis decoder) or "off" /
// "false" / "0" (legacy 72-dibit raw-MAC-PDU path, opt-out for
// pre-stripped fixtures). Ignored for non-P25-Phase-2 protocols.
P25Phase2TrellisMode string `yaml:"p25_phase2_trellis_mode"`
// P25Phase2RSMode enables the outer Reed-Solomon RS(24, 16, 9)
// verification layer on top of the trellis-decoded MAC PDU.
// Recognised values: "" / "off" / "false" / "0" (the default —
// no outer RS verification; matches historical decoder
// behaviour) or "on" / "true" / "1" (verify RS syndromes per
// TIA-102.BAAA-A §5.9; drop MAC PDUs whose syndromes are
// non-zero before parsing). Ignored for non-P25-Phase-2
// protocols.
P25Phase2RSMode string `yaml:"p25_phase2_rs_mode"`
// P25Phase2ScramblerMode enables the PN44 descrambling layer
// per TIA-102.BBAC-1 §7.2.5 on top of the trellis-decoded MAC
// PDU. Recognised values: "" / "off" / "false" / "0" (the
// default — no PN44 descrambling; matches historical decoder
// behaviour and synthesized-fixture expectations) or "on" /
// "true" / "1" (XOR the trellis-decoded 144-bit MAC PDU with
// the leading 144 bits of the PN44 sequence). The scrambler
// seed is derived from (WACN, SystemID, Color Code = NAC) per
// spec equation (5); the zero-seed edge case maps to (2^44 - 1).
// Full superframe-aware per-burst offset tracking is a
// follow-up. Ignored for non-P25-Phase-2 protocols.
P25Phase2ScramblerMode string `yaml:"p25_phase2_scrambler_mode"`
// P25Phase2ClockMode selects the symbol-timing-recovery strategy
// for the P25 Phase 2 receiver. Recognised values: "" /
// "gardner" / "on" (the new default — non-data-aided Gardner
// loop; recommended for live SDR captures) or "naive" / "off"
// (decimate every sps-th sample; works on sample-aligned
// synthesized IQ). Ignored for non-P25-Phase-2 protocols.
P25Phase2ClockMode string `yaml:"p25_phase2_clock_mode"`
// TETRAClockMode mirrors P25Phase2ClockMode for the TETRA
// receiver. Recognised values: "" / "gardner" / "on" (the new
// default) or "naive" / "off". Ignored for non-TETRA protocols.
TETRAClockMode string `yaml:"tetra_clock_mode"`
// NXDNViterbiMode enables the K=5 ½-rate Viterbi FEC decoder
// on the NXDN CAC region. Recognised values: "" / "spec" (the
// new default — full NXDN-TS-1-A §4.5.1.1 outbound CAC chain),
// "on" / "true" / "1" (intermediate 92-dibit K=5 Viterbi path
// for older MMDVMHost / DSDcc fixtures), or "off" / "false" /
// "0" (legacy 44-dibit raw-CAC path, opt-out for pre-stripped
// fixtures). Ignored for non-NXDN protocols.
NXDNViterbiMode string `yaml:"nxdn_viterbi_mode"`
// NXDNDeviationHz overrides the peak frequency deviation (Hz)
// the NXDN receiver's slicer is calibrated against. The Common
// Air Interface spec value is 1800 Hz (matched against the
// FM-discriminator output level so live captures slice
// correctly). Some on-air transmitters deviate from spec —
// captures whose dibit distribution is bimodal (outer ±3 levels
// dominate, inner ±1 underrepresented) usually want a higher
// value (e.g., 2400 Hz). Zero / unset uses the spec default.
// Ignored for non-NXDN protocols.
NXDNDeviationHz float64 `yaml:"nxdn_deviation_hz,omitempty"`
// EDACSBCHMode enables the BCH(40, 28, 2) FEC layer on the
// EDACS CCW. Recognised values: "" / "on" / "true" / "1" (the
// new default — 40-bit on-wire BCH decode with single/double-
// bit correction) or "off" / "false" / "0" (legacy pre-stripped
// 40-bit CCW, opt-out for pre-stripped fixtures). Ignored for
// non-EDACS protocols.
EDACSBCHMode string `yaml:"edacs_bch_mode"`
// MPT1327BCHMode enables the BCH(63, 38) FEC layer on the MPT
// 1327 codeword. Recognised values: "" / "on" / "true" / "1"
// (the new default — 64-bit on-wire BCH decode) or "off" /
// "false" / "0" (legacy 38-bit pre-stripped codeword, opt-out
// for pre-stripped fixtures). Ignored for non-MPT-1327
// protocols.
MPT1327BCHMode string `yaml:"mpt1327_bch_mode"`
// MPT1327CWSCTolerance sets the Hamming-distance threshold the
// Process adapter uses when scanning for the 16-bit Codeword
// Synchronisation Code that precedes every MPT 1327 message.
// Recognised values: "" → default 2-bit tolerance (matches
// commercial MPT 1327 receivers on noisy on-air captures);
// "0" / "exact" / "off" → exact match (use for pre-stripped
// synthesized fixtures); a decimal integer in [0, 15] for
// custom thresholds. Ignored for non-MPT-1327 protocols.
MPT1327CWSCTolerance string `yaml:"mpt1327_cwsc_tolerance"`
// MotorolaBCHMode enables the BCH(64, 16, 11) FEC layer on the
// Motorola Type II OSW. Recognised values: "" / "on" / "true" /
// "1" (the new default — two 64-bit BCH(64, 16, 11) codewords
// reassembled into the 32-bit OSW with single- through 11-bit-
// error correction) or "off" / "false" / "0" (legacy 32-bit
// raw-OSW path, opt-out for pre-stripped fixtures). Ignored
// for non-Motorola protocols.
MotorolaBCHMode string `yaml:"motorola_bch_mode"`
// DStarFECMode enables the JARL DV-mode header FEC chain on
// the D-STAR Process adapter (conv R=1/2 K=5 + PN15 scrambler
// + 22×30 block interleaver). Recognised values: "" / "off" /
// "false" / "0" (the default — 328 info bits straight off the
// wire) or "on" / "true" / "1" (660 on-wire bits → full FEC
// chain → 328 info bits → ParseHeader). Ignored for non-D-STAR
// protocols.
DStarFECMode string `yaml:"dstar_fec_mode"`
}
type ToneOutConfig ¶
type ToneOutConfig struct {
Profiles []ToneProfileConfig `yaml:"profiles"`
}
ToneOutConfig describes paging-tone profiles to monitor. Empty Profiles disables the detector. Each ToneProfileConfig maps to one internal/voice/toneout.Profile.
type ToneProfileConfig ¶
type ToneProfileConfig struct {
Name string `yaml:"name"`
AlphaTag string `yaml:"alpha_tag"`
Tones []ToneProfileToneConfig `yaml:"tones"`
ToleranceHz float64 `yaml:"tolerance_hz"`
MagnitudeThreshold float64 `yaml:"magnitude_threshold"`
MaxGap string `yaml:"max_gap"`
Cooldown string `yaml:"cooldown"`
System string `yaml:"system"`
GroupID uint32 `yaml:"group_id"`
}
ToneProfileConfig is the YAML shape of one tone-out alarm.
- For two-tone sequential paging (most US fire/EMS) supply two entries in `tones`: A-tone first, then B-tone.
- For single-tone supervision pages supply one tone.
Durations are Go duration strings ("250ms", "1.5s"). MaxDuration of 0 disables the upper bound.
type ToneProfileToneConfig ¶
type ToneProfileToneConfig struct {
FrequencyHz float64 `yaml:"frequency_hz"`
MinDuration string `yaml:"min_duration"`
MaxDuration string `yaml:"max_duration"`
}
ToneProfileToneConfig is one tone within a profile sequence.
type TrunkingConfig ¶
type TrunkingConfig struct {
Systems []SystemConfig `yaml:"systems"`
}
type Writer ¶ added in v0.1.5
type Writer struct {
// contains filtered or unexported fields
}
Writer serialises in-place edits to a config.yaml so concurrent callers (settings PATCH, SIGHUP-driven reloads, import commits) can't tear each other's writes. The writer also enforces an mtime guard so externally-edited files aren't clobbered.
func NewWriter ¶ added in v0.1.5
NewWriter constructs a Writer bound to path. The path must point at an existing file; an empty path returns nil so callers can disable the live-edit surface gracefully.
func (*Writer) WritePatch ¶ added in v0.1.5
WritePatch loads the file, runs Patch.Apply against the parsed config, runs Validate, then mutates the underlying yaml.Node tree so unrelated content (comments, formatting, keys we don't know about) is preserved, and atomically writes the result back.
Returns the patched Config so callers can hand it to in-process subsystems for hot-reload.