mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
idle service and lght lock improvements
This commit is contained in:
@@ -187,9 +187,13 @@ function HomeAssistantControlsContent() {
|
||||
const ha = useSessionSelector((state) => state.session?.homeAssistant || null);
|
||||
const { homeAssistantToggle, homeAssistantSetLightColor, homeAssistantSetLightWhite } =
|
||||
useSessionActions();
|
||||
const role = useSessionSelector((state) => state.session?.role || null);
|
||||
const mode = useSessionSelector((state) => state.session?.mode || null);
|
||||
const entities = useMemo(() => ha?.entities || [], [ha?.entities]);
|
||||
const lightPolicy = ha?.lightPolicy || null;
|
||||
const controlsLocked = Boolean(lightPolicy?.locked || lightPolicy?.lockedOn);
|
||||
const adminCanControlLockedLights = role === 'lockdown' || (role === 'admin' && mode !== 'lockdown');
|
||||
const lightPolicyLocked = Boolean(lightPolicy?.locked || lightPolicy?.lockedOn);
|
||||
const controlsLocked = lightPolicyLocked && !adminCanControlLockedLights;
|
||||
const lockState = lightPolicy?.lockState || (lightPolicy?.lockedOn ? 'on' : null);
|
||||
const onKeyLabel = formatKeyLabel(keymap?.homeAssistantOn?.[0]);
|
||||
const offKeyLabel = formatKeyLabel(keymap?.homeAssistantOff?.[0]);
|
||||
@@ -224,18 +228,22 @@ function HomeAssistantControlsContent() {
|
||||
{offKeyLabel ? <KeyPill label={offKeyLabel} /> : null}
|
||||
</span>
|
||||
</div>
|
||||
{controlsLocked ? <StatusBadge label={lockState === 'off' ? 'Locked Off' : 'Locked On'} tone="warn" /> : null}
|
||||
{lightPolicyLocked ? <StatusBadge label={lockState === 'off' ? 'Locked Off' : 'Locked On'} tone="warn" /> : null}
|
||||
<StatusBadge label={connected ? 'Connected' : 'Offline'} tone={connected ? 'success' : 'warn'} />
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<CardFrame title="Room Controls" actions={actions} bodyClassName="space-y-0.5 text-base">
|
||||
{controlsLocked ? (
|
||||
{lightPolicyLocked ? (
|
||||
<p className="rounded border border-amber-600/60 bg-amber-900/40 px-1 py-0.5 text-xs text-amber-100">
|
||||
{lockState === 'off'
|
||||
? 'Lights are locked off. Room controls are disabled.'
|
||||
: 'Lights are locked on. Room controls are disabled.'}
|
||||
{adminCanControlLockedLights
|
||||
? lockState === 'off'
|
||||
? 'Lights are locked off. Admin room controls remain available.'
|
||||
: 'Lights are locked on. Admin room controls remain available.'
|
||||
: lockState === 'off'
|
||||
? 'Lights are locked off. Room controls are disabled.'
|
||||
: 'Lights are locked on. Room controls are disabled.'}
|
||||
</p>
|
||||
) : null}
|
||||
<div className="grid grid-cols-1 gap-0.5 sm:grid-cols-2 lg:grid-cols-3">
|
||||
|
||||
@@ -168,7 +168,12 @@ export function ControlSystemProvider({ children }) {
|
||||
: true;
|
||||
const roverId = useSessionSelector((state) => state.session?.assignment?.roverId ?? null);
|
||||
const homeAssistantEntities = useSessionSelector((state) => state.session?.homeAssistant?.entities ?? []);
|
||||
const roomLightsLockedOn = useSessionSelector((state) => Boolean(state.session?.homeAssistant?.lightPolicy?.lockedOn));
|
||||
const roomLightsLocked = useSessionSelector((state) =>
|
||||
Boolean(state.session?.homeAssistant?.lightPolicy?.locked || state.session?.homeAssistant?.lightPolicy?.lockedOn),
|
||||
);
|
||||
const roomLightsLockedOn = useSessionSelector((state) =>
|
||||
Boolean(state.session?.homeAssistant?.lightPolicy?.lockedOn),
|
||||
);
|
||||
const { homeAssistantSetState } = useSessionActions();
|
||||
const overcurrentLimiter = useOvercurrentLimiter(roverId);
|
||||
const driveTransform = useCallback(
|
||||
@@ -183,6 +188,17 @@ export function ControlSystemProvider({ children }) {
|
||||
const ptzControls = usePtzControlAdapter();
|
||||
|
||||
const turnOnAllLights = useCallback(() => {
|
||||
/*
|
||||
Automatic drive-mode lighting is convenience behavior for the open room.
|
||||
A room-light lock is an explicit policy decision, including locked-off,
|
||||
so this helper must not issue any Home Assistant commands while that
|
||||
policy is active. Admins can still use the dedicated room controls when
|
||||
they need to override individual lamps.
|
||||
*/
|
||||
if (roomLightsLocked) {
|
||||
pendingLightsRef.current = false;
|
||||
return;
|
||||
}
|
||||
const entities = homeAssistantEntities || [];
|
||||
const targets = entities.filter(
|
||||
(ent) =>
|
||||
@@ -200,7 +216,7 @@ export function ControlSystemProvider({ children }) {
|
||||
});
|
||||
// Give the loop a chance; clear pending after issuing commands.
|
||||
pendingLightsRef.current = false;
|
||||
}, [homeAssistantEntities, homeAssistantSetState]);
|
||||
}, [homeAssistantEntities, homeAssistantSetState, roomLightsLocked]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({ type: 'control/set-rover', payload: pipeline.roverId });
|
||||
|
||||
@@ -108,6 +108,9 @@ export default function KeyboardInputManager() {
|
||||
const roverId = useControlSelector((control) => control.state.roverId);
|
||||
const hornActive = useControlSelector((control) => Boolean(control.state.horn?.active));
|
||||
const homeAssistant = useSessionSelector((state) => state.session?.homeAssistant || null);
|
||||
const role = useSessionSelector((state) => state.session?.role || null);
|
||||
const mode = useSessionSelector((state) => state.session?.mode || null);
|
||||
const adminCanControlLockedLights = role === 'lockdown' || (role === 'admin' && mode !== 'lockdown');
|
||||
const dockAssist = useManualDockAssist();
|
||||
const { homeAssistantSetState, pushAlert } = useSessionActions();
|
||||
const { focusChat } = useChatActions();
|
||||
@@ -310,7 +313,14 @@ export default function KeyboardInputManager() {
|
||||
const latest = latestRef.current;
|
||||
const ha = latest?.homeAssistant;
|
||||
if (!ha?.enabled || !ha?.connected) return;
|
||||
if (ha?.lightPolicy?.locked || ha?.lightPolicy?.lockedOn) return;
|
||||
/*
|
||||
Room-light lock disables keyboard cycling for normal users because those
|
||||
shortcuts are part of the public room-control surface. Admin sessions are
|
||||
allowed through when the current site mode would also allow their socket
|
||||
command, so keyboard behavior matches the server-side authorization and
|
||||
the clickable Room Controls panel.
|
||||
*/
|
||||
if ((ha?.lightPolicy?.locked || ha?.lightPolicy?.lockedOn) && !latest?.adminCanControlLockedLights) return;
|
||||
const entities = ha.entities || [];
|
||||
const eligible = entities.filter(
|
||||
(ent) =>
|
||||
@@ -371,6 +381,7 @@ export default function KeyboardInputManager() {
|
||||
homeAssistant,
|
||||
homeAssistantSetState,
|
||||
isChatFocused,
|
||||
adminCanControlLockedLights,
|
||||
keyboardSpeeds,
|
||||
keymap,
|
||||
nudgeServo,
|
||||
|
||||
Reference in New Issue
Block a user