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.
75 lines
2.4 KiB
Go
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)
|
|
}
|