diff --git a/internal/powergenius/powergenius.go b/internal/powergenius/powergenius.go index f2907b2..fc3e6ad 100644 --- a/internal/powergenius/powergenius.go +++ b/internal/powergenius/powergenius.go @@ -45,6 +45,10 @@ type Client struct { statusMu sync.RWMutex status Status + // Optimistic fan mode kept until the amp's status poll confirms it (or it + // ages out) — otherwise a stale poll right after a change reverts the UI. + fanPending string + fanPendingAt time.Time cmdID atomic.Int64 stop chan struct{} @@ -102,7 +106,10 @@ func (c *Client) SetFanMode(mode string) error { if _, err := c.command("setup fanmode=" + m); err != nil { return err } - c.setStatus(func(s *Status) { s.FanMode = m }) // optimistic + c.statusMu.Lock() + c.status.FanMode = m // optimistic + c.fanPending, c.fanPendingAt = m, time.Now() + c.statusMu.Unlock() return nil } @@ -217,7 +224,13 @@ func (c *Client) parse(resp string) { case "state": c.status.State = kv[1] case "fanmode": - c.status.FanMode = strings.ToUpper(kv[1]) + dev := strings.ToUpper(kv[1]) + // Honour a recent optimistic change until the amp confirms it. + if c.fanPending != "" && time.Since(c.fanPendingAt) < 3*time.Second && dev != c.fanPending { + break + } + c.fanPending = "" + c.status.FanMode = dev case "temp": c.status.Temperature, _ = strconv.ParseFloat(kv[1], 64) } diff --git a/internal/ultrabeam/ultrabeam.go b/internal/ultrabeam/ultrabeam.go index e4e5523..81e080c 100644 --- a/internal/ultrabeam/ultrabeam.go +++ b/internal/ultrabeam/ultrabeam.go @@ -68,6 +68,13 @@ type Client struct { running bool seqNum byte seqMu sync.Mutex + + // Optimistic pattern direction kept until the antenna's status poll reports + // it (or it ages out) — the motors take a second or two, and a stale poll in + // between would otherwise snap the UI back to the old direction. + pendingDir int + pendingDirAt time.Time + pendingDirSet bool } type Status struct { @@ -199,6 +206,14 @@ func (c *Client) pollLoop() { } c.statusMu.Lock() + // Keep a just-commanded direction until the antenna reports it. + if c.pendingDirSet { + if time.Since(c.pendingDirAt) > 4*time.Second || status.Direction == c.pendingDir { + c.pendingDirSet = false + } else { + status.Direction = c.pendingDir + } + } c.lastStatus = status c.statusMu.Unlock() @@ -449,6 +464,14 @@ func (c *Client) SetFrequency(freqKhz int, direction int) error { } _, err := c.sendCommand(CMD_FREQ, data) + if err == nil { + c.statusMu.Lock() + c.pendingDir, c.pendingDirAt, c.pendingDirSet = direction, time.Now(), true + if c.lastStatus != nil { + c.lastStatus.Direction = direction // reflect immediately + } + c.statusMu.Unlock() + } return err }