Files
OpsLog/hrdlogonair.go
T
rouggy 784d809290 fix(rotator): put the SP/LP readout inside the compass itself
It went under the Station Control rotator; the compass that wanted it is the
docked one beside the entry strip. Both are the same RotorCompass, so the
readout moves INTO that component: every compass in the app carries it, and no
caller draws its own.

The bezel already showed the short path as a red marker, but a marker is a
direction, not a number — and the numbers in the status bar are 10px, which is
what prompted this.

Clickable only when the caller passed onGoto, since a compass rendered without
one cannot turn anything and a button that does nothing is worse than a label.
2026-08-13 11:45:49 +02:00

75 lines
2.4 KiB
Go

package main
// HRDLog "ON AIR" — publishing the live frequency, mode and rig on hrdlog.net,
// so the site shows "F4BPO is on air 14,074,000 FT8 IC-7300" while the station
// is operating.
//
// The endpoint and its field names come from HRDLog's own library
// (github.com/iw1qlh/HRDLOG-net-library), not from reading someone's traffic.
import (
"context"
"strings"
"time"
"hamlog/internal/applog"
"hamlog/internal/extsvc"
)
// onAirEvery is how often the status is refreshed. HRDLog drops a station from
// the on-air list when it stops hearing from it, so this is a heartbeat, not a
// change notification.
const onAirEvery = 2 * time.Minute
// hrdlogOnAirLoop publishes while the option is on and the rig is readable.
func (a *App) hrdlogOnAirLoop() {
defer func() { _ = recover() }() // never crash the app from a status broadcast
t := time.NewTicker(onAirEvery)
defer t.Stop()
for range t.C {
a.publishHRDLogOnAir()
}
}
// publishHRDLogOnAir sends one update. Silent when switched off, unconfigured,
// or when the rig has nothing to report — an announcement with no frequency
// would say the operator is on air on 0 Hz.
func (a *App) publishHRDLogOnAir() {
cfg := a.loadExternalServices().HRDLog
if !cfg.OnAir || strings.TrimSpace(cfg.Callsign) == "" || strings.TrimSpace(cfg.Code) == "" {
return
}
if a.cat == nil {
return
}
st := a.cat.State()
if !st.Connected || st.FreqHz <= 0 {
return
}
// The rig NAME as the operator knows it — that string is what the site
// displays. The active profile's MyRig first, since it is what every QSO is
// stamped with; the CAT backend's own model only when the profile has none.
radio := ""
if a.profiles != nil {
if pr, err := a.profiles.Active(a.ctx); err == nil {
radio = strings.TrimSpace(pr.MyRig)
}
}
if radio == "" {
radio = strings.TrimSpace(st.Rig)
}
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
msg, err := extsvc.SendHRDLogOnAir(ctx, nil, cfg.Callsign, cfg.Code, st.FreqHz, st.Mode, radio)
if err != nil {
// Logged, never surfaced: this is a broadcast the operator did not ask
// for at this instant, and a toast every two minutes on a flaky link
// would be worse than the missing status.
applog.Printf("hrdlog on-air: %v (%s)", err, msg)
return
}
applog.Printf("hrdlog on-air: %s %.3f MHz %s (%s) — %s",
cfg.Callsign, float64(st.FreqHz)/1e6, st.Mode, radio, msg)
}