Fix fixture process transitions
This commit is contained in:
@@ -32,6 +32,9 @@ Singleton {
|
||||
property bool actionStreamFinished: false
|
||||
property bool actionExited: false
|
||||
property int actionExitCode: 0
|
||||
property bool fixtureTransitionDraining: false
|
||||
property bool fixtureTransitionStreamFinished: false
|
||||
property bool fixtureTransitionExited: false
|
||||
|
||||
readonly property var visibleEntities: root.selectedEntities.slice(0, 4)
|
||||
readonly property int discoveredCount: root.catalog.length
|
||||
@@ -193,8 +196,12 @@ Singleton {
|
||||
}
|
||||
|
||||
function startNextAction(): void {
|
||||
if (actionProc.running || root.activeAction !== null || root.actionQueue.length === 0)
|
||||
if (root.fixtureTransitionDraining
|
||||
|| actionProc.running
|
||||
|| root.activeAction !== null
|
||||
|| root.actionQueue.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
root.activeAction = root.actionQueue[0];
|
||||
root.actionResponseText = "";
|
||||
@@ -220,6 +227,11 @@ Singleton {
|
||||
}
|
||||
|
||||
function handleActionStreamFinished(text: string): void {
|
||||
if (root.fixtureTransitionDraining) {
|
||||
root.fixtureTransitionStreamFinished = true;
|
||||
fixtureTransitionTimer.restart();
|
||||
return;
|
||||
}
|
||||
if (root.activeAction === null || root.actionStreamFinished)
|
||||
return;
|
||||
root.actionResponseText = text;
|
||||
@@ -228,6 +240,11 @@ Singleton {
|
||||
}
|
||||
|
||||
function handleActionExited(exitCode: int): void {
|
||||
if (root.fixtureTransitionDraining) {
|
||||
root.fixtureTransitionExited = true;
|
||||
fixtureTransitionTimer.restart();
|
||||
return;
|
||||
}
|
||||
if (root.activeAction === null || root.actionExited)
|
||||
return;
|
||||
root.actionExited = true;
|
||||
@@ -350,13 +367,49 @@ Singleton {
|
||||
root.actionExitCode = 0;
|
||||
}
|
||||
|
||||
function beginFixtureTransition(): void {
|
||||
const shouldDrain = root.fixtureMode
|
||||
&& root.fixtureProcessMode !== ""
|
||||
&& (actionProc.running || root.activeAction !== null);
|
||||
const streamAlreadyFinished = root.actionStreamFinished;
|
||||
const exitAlreadyObserved = root.actionExited;
|
||||
|
||||
fixtureTransitionTimer.stop();
|
||||
root.fixtureTransitionDraining = shouldDrain;
|
||||
root.fixtureTransitionStreamFinished = shouldDrain && streamAlreadyFinished;
|
||||
root.fixtureTransitionExited = shouldDrain && exitAlreadyObserved;
|
||||
root.resetActionState();
|
||||
|
||||
if (!shouldDrain)
|
||||
return;
|
||||
if (actionProc.running)
|
||||
actionProc.running = false;
|
||||
fixtureTransitionTimer.restart();
|
||||
}
|
||||
|
||||
function tryFinishFixtureTransition(): void {
|
||||
if (!root.fixtureTransitionDraining)
|
||||
return;
|
||||
if (actionProc.running) {
|
||||
fixtureTransitionTimer.restart();
|
||||
return;
|
||||
}
|
||||
if (!root.fixtureTransitionStreamFinished || !root.fixtureTransitionExited)
|
||||
return;
|
||||
|
||||
root.fixtureTransitionDraining = false;
|
||||
root.fixtureTransitionStreamFinished = false;
|
||||
root.fixtureTransitionExited = false;
|
||||
queueAdvanceTimer.restart();
|
||||
}
|
||||
|
||||
function applyFixture(name: string): void {
|
||||
if (["ready", "stale", "unavailable", "missing-selected", "action-error",
|
||||
"process-actions", "process-no-output"].indexOf(name) < 0)
|
||||
return;
|
||||
|
||||
root.beginFixtureTransition();
|
||||
root.fixtureMode = true;
|
||||
root.resetActionState();
|
||||
root.fixtureProcessMode = name === "process-actions"
|
||||
? "success"
|
||||
: (name === "process-no-output" ? "no-output" : "");
|
||||
@@ -389,6 +442,7 @@ Singleton {
|
||||
}
|
||||
|
||||
function clearFixture(): void {
|
||||
root.beginFixtureTransition();
|
||||
root.fixtureMode = false;
|
||||
root.fixtureProcessMode = "";
|
||||
root.phase = "loading";
|
||||
@@ -397,7 +451,6 @@ Singleton {
|
||||
root.fixtureFavorites = [];
|
||||
root.stale = false;
|
||||
root.lastError = "";
|
||||
root.resetActionState();
|
||||
root.refresh();
|
||||
}
|
||||
|
||||
@@ -427,6 +480,8 @@ Singleton {
|
||||
id: queueAdvanceTimer
|
||||
interval: 0
|
||||
onTriggered: {
|
||||
if (root.fixtureTransitionDraining)
|
||||
return;
|
||||
if (actionProc.running) {
|
||||
queueAdvanceTimer.restart();
|
||||
return;
|
||||
@@ -435,6 +490,12 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: fixtureTransitionTimer
|
||||
interval: 0
|
||||
onTriggered: root.tryFinishFixtureTransition()
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 60000
|
||||
repeat: true
|
||||
|
||||
@@ -45,12 +45,15 @@ trap cleanup EXIT
|
||||
|
||||
start_test_shell() {
|
||||
stop_test_shell || fail 'pre-existing branch shell did not stop cleanly'
|
||||
qs_for_test --daemonize >"$shell_log" 2>&1
|
||||
for _ in $(seq 1 80); do
|
||||
if qs_for_test ipc show 2>/dev/null | rg '^target home-assistant$' >/dev/null; then
|
||||
return
|
||||
fi
|
||||
sleep 0.1
|
||||
for _attempt in 1 2; do
|
||||
qs_for_test --daemonize >"$shell_log" 2>&1
|
||||
for _ in $(seq 1 80); do
|
||||
if qs_for_test ipc show 2>/dev/null | rg '^target home-assistant$' >/dev/null; then
|
||||
return
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
stop_test_shell || fail 'failed branch-shell attempt did not stop cleanly'
|
||||
done
|
||||
sed -n '1,200p' "$shell_log" >&2
|
||||
fail 'isolated branch shell did not start'
|
||||
@@ -185,6 +188,27 @@ wait_for_home_status '
|
||||
(.entities[] | select(.id == "light.fixture_hall") | .active == true)
|
||||
' 'nonzero no-output Home action did not fail safely and continue the queue'
|
||||
|
||||
qs_for_test ipc call home-assistant fixture process-actions >/dev/null
|
||||
qs_for_test ipc call home-assistant brightness light.fixture_living 88 >/dev/null
|
||||
jq -e '
|
||||
.busyEntityIds == ["light.fixture_living"] and
|
||||
.pendingBrightness["light.fixture_living"] == 88
|
||||
' <<<"$(qs_for_test ipc call home-assistant status)" >/dev/null \
|
||||
|| fail 'fixture transition setup did not start an in-flight action'
|
||||
qs_for_test ipc call home-assistant fixture process-no-output >/dev/null
|
||||
qs_for_test ipc call home-assistant toggle light.fixture_hall >/dev/null
|
||||
wait_for_home_status '
|
||||
.phase == "ready" and
|
||||
.busy == false and
|
||||
.busyEntityIds == [] and
|
||||
.pendingBrightness == {} and
|
||||
.entityErrors == {} and
|
||||
(.entities[] |
|
||||
select(.id == "light.fixture_living") |
|
||||
.active == false and .brightnessPct == 36) and
|
||||
(.entities[] | select(.id == "light.fixture_hall") | .active == true)
|
||||
' 'switching process fixtures stranded or misattributed the new action'
|
||||
|
||||
qs_for_test ipc call home-assistant fixture missing-selected >/dev/null
|
||||
jq -e '
|
||||
.fixture == true and
|
||||
|
||||
Reference in New Issue
Block a user