From 59ab1beb9bc1dc3b2d448560531b88d47fb57613 Mon Sep 17 00:00:00 2001 From: Autumn Date: Sat, 16 May 2026 10:29:27 +0100 Subject: [actions] added motion sensor support --- src/lib/helpers/action.ts | 70 ++++++++++++++++++++++++++++++++++++++++++----- src/lib/init.ts | 35 ++++++++++++++++++++++-- 2 files changed, 96 insertions(+), 9 deletions(-) diff --git a/src/lib/helpers/action.ts b/src/lib/helpers/action.ts index 59677ea..87364ba 100644 --- a/src/lib/helpers/action.ts +++ b/src/lib/helpers/action.ts @@ -7,14 +7,10 @@ import { sendMessage } from "@lib/mqtt.ts" import allActions from "@lib/config/actions.ts" import allDevices from "@lib/config/devices.ts" -// run on button press -export function onPress(action) { - - console.debug(`-> running ${action.id}`) +// run actions +function _runActions(actions) { - const actionDo = action.do - - actionDo.forEach((action) => { + actions.forEach((action) => { const device = allDevices.find((device) => device.id === action.device) @@ -29,6 +25,66 @@ export function onPress(action) { }) } +// run on button press +export function onPress(action) { + + console.debug(`-> running ${action.id}`) + + _runActions(action.do) +} + +// run on motion +export function onMotion(action, payload) { + + if (payload.presence === true) { + + console.debug(`-> running ${action.id}`) + + if (!global.activeActions.includes(action.id)) { + global.activeActions.push(action.id) + } + + if (global.activeUndos.includes(action.id)) { + global.activeUndos = global.activeUndos.filter((trigger) => trigger !== action.id) + } + + _runActions(action.do) + + } else { + + if (global.activeActions.includes(action.id)) { + + console.debug(`-> undoing ${action.id}`) + + const inverseActions = action.do.map((inverseAction) => { + let actionDo + + switch (inverseAction.action) { + case "on": + actionDo = "off" + break + + case "off": + actionDo = "on" + break + + default: + actionDo = inverseAction.action + } + + return { + ...inverseAction, + action: actionDo + } + }) + + global.activeActions = global.activeActions.filter((trigger) => trigger !== action.id) + + _runActions(inverseActions) + } + } +} + // validate actions config export function validate() { diff --git a/src/lib/init.ts b/src/lib/init.ts index 03c9b63..99730e9 100644 --- a/src/lib/init.ts +++ b/src/lib/init.ts @@ -3,7 +3,7 @@ // // imports -import { validate, onPress } from "@lib/helpers/action.ts" +import { validate, onPress, onMotion } from "@lib/helpers/action.ts" import { addListener } from "@lib/mqtt.ts" import allActions, { ACTION_ON_ACTION } from "@lib/config/actions.ts" import allDevices from "@lib/config/devices.ts" @@ -11,6 +11,9 @@ import allDevices from "@lib/config/devices.ts" // initialise actions function _initActions() { + global.activeActions = [] + global.activeUndos = [] + if (!allActions || allActions.length < 1) return allActions.forEach((action) => { @@ -24,7 +27,21 @@ function _initActions() { return } - const topic = `${onDevice.mqtt}/action` + // todo: use a single callback / listener & just subscribe to each topic + // first param on return is the topic so case / switch that + + let topic + + if (["on", "off", "toggle"].includes(action.on)) { + + topic = `${onDevice.mqtt}/action` + + } else { + + topic = onDevice.mqtt + + } + const callback = (message) => { const messageAction = message.toString() @@ -52,6 +69,20 @@ function _initActions() { break + default: + + // probbaly a json string + const jsonMessageAction = JSON.parse(messageAction) + + if (jsonMessageAction?.presence !== undefined && action.on.action === "motion") { + + onMotion(action, jsonMessageAction) + + } else { + + console.warn(`?> unknown action: ${messageAction} from ${topic}`) + + } } } -- cgit v1.3