I am developing a UI that controls various hardware components like lights, appliances, and such. The hardware sends notifications when its state changes. The UI receives a live stream of the state from the hardware. The UI can send commands to the hardware to modify its state (ex: turn a light on/off). It follows a CQRS pattern if you are familiar with that. Sometimes these commands fail for various reasons (loss of connectivity, hardware failure, ...) and there could be a decent amount of latency.
I want to indicate the current state of a hardware component and allow the user to control its state. The following are some possible approaches that I have considered. I'm using turning a light on/off as an example.
- UI overrides reported state with expected state till confirmed or a timeout. In this approach a toggle switch indicates the state of the light and controls it. When the switch is toggled from off to on the UI immediately indicates the state as on but the control is disabled till the state change is confirmed by a message from the light. If a message is not received within X seconds then the control is enabled and reverted to its previous known state. The user is then notified that their change didn't work. Any state messages that come in for the light that don't match the expected state are overridden due to the non-deterministic nature of the event stream.
- Use stateless controls and display state separately. In this approach an on and off button exist and a label that indicates the current state. The buttons don't indicate state. When pressed they send the associated command (turn the light on or off). The state label doesn't indicate a change till it receives a message from the light. I should probably give feedback to the user on "in-flight" commands. I might should prevent the user from sending a command to change to the state the component is already in.
I need to control states that have options and ranges. I have currently implemented the first option and am using toggles (binary), radio buttons (for more than two modes), and sliders (numeric ranges). It is a bit complex and I feel that it may be confusing for the users when reality doesn't match the UI. For the second option I am unsure about what controls to use and how much it will bloat the UI.
I'm open to alternate approaches. I don't want the user to act off of an inaccurate understanding of the state or be confused by UI state not matching what they see in the hardware.
Should the control indicate the state or should state and control be separated? If state and control should be separated, then what controls should be used for options and ranges and how should they be correlated to the current state? How should feedback be given to the user about "in-flight" commands.