Skip to content

Monitor Part 3(and 4) of 5 - Rig Status Indicators - #92

Open
tekstrand wants to merge 4 commits into
JS8Call-improved:masterfrom
tekstrand:rig-indicator
Open

Monitor Part 3(and 4) of 5 - Rig Status Indicators#92
tekstrand wants to merge 4 commits into
JS8Call-improved:masterfrom
tekstrand:rig-indicator

Conversation

@tekstrand

Copy link
Copy Markdown
Contributor

Parts

  1. AudioDevices extraction (Monitor status bar 1/5: Extract audio device handling into AudioDevices #90, merged)
  2. The status strip itself, with the audio picker behind an overflow menu (Monitor Part 2 of 5 - Simplify Monitor Controls UI #91, merged)
  3. Rig link indicator on the strip, fed by a new rig status broadcast (this PR)
  4. Error state display (this PR, combined with 3)
  5. The same audio device selection in Settings

What

  1. Adds a rig link icon beside the state word, shown only when rig control is enabled in Settings
  2. Adds a rig status broadcast to the service that polls every two seconds while the engine runs and reports only on a change
  3. Draws a warning glyph in place of the state dot in the error state
  4. Send all freq selections to the service instead of checking the rig type in the fragment first

Why

  1. Better to have status and rig as separate indicators, IMO.
  2. The connection flags are set in too many places to broadcast from each one.
  3. Transmitting and Error are both red. A different shape is easier to see, especially for color blind folks.
  4. The selectFrequency change I mentioned in Monitor Part 2 of 5 - Simplify Monitor Controls UI #91. The fragment had a "duplicate" list of which rigs can set frequency. It also showed a snackbar saying the frequency was being set even when the rig never connected. Now the service decides and reports failures via broadcast. Success is silent and failures notify. With rig control off the freq selection is silent and stores the value the service reads back at startup.

Test

  1. ./gradlew :app:testDebugUnitTest
  2. On the Fire HD 10 profile emulator: no indicator with rig control off, grey beside Off with it on, and starting against a network rig with nothing listening ends red glyph, red Error, red icon. Frequency picks reach the service in every case; with rig control off they just store the dial value, and with the dead rig the pick stays quiet since the failed start already showed the rig error.

Screenshots

rig-indicator-error-red rig-indicator-configured-grey rig-indicator-off

A rig icon appears beside the state word when rig control is switched on in Settings. It is grey before the engine tries, amber while starting, green when CAT is alive and red when a running or failed engine has no link, which are the colors the state dot already uses for the same ideas. The service reports the link through a new rig status broadcast: the connection flags are assigned in too many places to report from each one, so it polls every two seconds while the engine runs and broadcasts only on a change. The flag records the last connect result, so a rig unplugged mid session still reads as connected until something tries to use it, and stopping reports the link down, since it cannot outlive the engine that opened it.

The error state draws a warning glyph in place of the dot. Transmitting and Error are both red, in shades close enough to be hard to tell apart at a glance, and red stays on Transmitting since red for on air is the convention. Shape rather than another shade also keeps the strip readable for the red and green color vision deficiencies, which matters here because receiving and transmitting already lean on those two colors.
…g types accept it. The fragment carried its own list of frequency capable rig types next to a snackbar that claimed the frequency was being set, but the list was a copy of the dispatch table the service already owns, and the claim was wrong whenever the rig was configured but never connected. The service drops a request without a rig link and reports a real failure through the error broadcast, so the pick is now quiet when it works and loud when it fails, and adding a rig type no longer means remembering a fragment. The pick also reaches the service with rig control off, which only sets the dial value the service would read back from the last_frequency preference anyway.
@tekstrand

Copy link
Copy Markdown
Contributor Author

I'm not comfortable merging it without testing this with a real rig and I'm away from my actual rigs right now. I'd either want to wait until I have a chance to do it(maybe later this week) or if you have bandwidth to help test that could work to.

@punk-kaos

Copy link
Copy Markdown
Contributor

I'm not comfortable merging it without testing this with a real rig and I'm away from my actual rigs right now. I'd either want to wait until I have a chance to do it(maybe later this week) or if you have bandwidth to help test that could work to.

That seems sensible.

I found one state-sync edge case with the rig status broadcast.

The service only broadcasts when the connected state changes, but a newly created MonitorViewModel starts with rigConnected = false. If the rig was already connected before the Activity/ViewModel was recreated, the service’s lastRigConnected is already true, so the poller won’t send another update. The new UI can then stay stuck showing disconnected until the rig actually changes state.

Since LocalBroadcastManager isn’t sticky, I think the simplest fix is probably to broadcast the current rig state on every 2-second poll, or otherwise add a way for the UI to explicitly request the current status when it attaches.

…d. The nav rail moves between tabs with the Navigation Component, which destroys the Monitor fragment's view on the way out and inflates a fresh one on the way back while keeping the fragment instance. The fresh views come up at their layout defaults, Off with a grey dot and the rig icon gone, but lastLabelRes, lastColorRes, lastRigColorRes and lastRigDescRes are fields on the instance and still hold the values from before the trip. With the engine running the first paint after the return computed Receiving, matched the stale memo, and skipped, so the strip sat on Off with the switch on and the waterfall scrolling underneath. Sending a heartbeat is the easiest way to hit it, since that is a trip to the Transmit tab and back. Clearing the four fields in onViewCreated makes the first paint of every new view unconditional. Verified on the Fire HD 10 with the rig attached: engine on, over to Transmit, back to Monitor, and the strip still reads Receiving with the green rig icon.
…he poller gated its broadcast behind a last-sent flag, which reads as tidy but breaks the moment the UI is not the same UI that heard the first one. Local broadcasts are not sticky, so a MonitorViewModel created after the rig connected starts at disconnected and never hears otherwise until the rig actually changes state, and the same thing happens to a ViewModel that missed a change while the activity was stopped with its receivers unregistered. Sending the current state every two seconds while the engine runs closes both, and it costs nothing on the UI side because the fragment already skips a paint whose color and description have not moved. The gate and its field are gone. Found in review on PR 92.
@tekstrand

Copy link
Copy Markdown
Contributor Author

♻️

The change gate is gone, poller sends the current state every 2s while the engine runs. It also covers a rig dropping while the app is backgrounded, since those broadcasts were being lost too.

Engine state has the same problem after an activity recreation, but that predates this PR, so I'll go file an issue for it.

Tested on a real rig. Found a bug where the strip froze on Off after a trip to the Transmit tab and back, because navigation recreates the fragment view but the repaint memo wasn't reset. Fixed in eec4eb9. It also surfaced two bugs on master, #93 and #94, filed separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants