From 95a251518992a56a4a719c684bc8fe050bb6dde9 Mon Sep 17 00:00:00 2001 From: bes-r Date: Wed, 20 May 2026 20:42:12 +0200 Subject: [PATCH] Prevent spoke triggers --- detached-script.js | 63 +++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/detached-script.js b/detached-script.js index d7e036f..c45eae0 100644 --- a/detached-script.js +++ b/detached-script.js @@ -1,13 +1,10 @@ // ============================================================================= -// Shelly 2PM Detached Script v3.4 +// Shelly 2PM Detached Script v3.5 // ============================================================================= -// Based on v3.3 (stable) -// Fix: supports both state-based and event-based inputs (Gen4 compatible) -// Fully English logging & events +// More stable version: counts only btn_down events. +// This reduces ghost triggers caused by extra btn_up / bounce events. // ============================================================================= -// === CONFIG ================================================================== - var CONFIG = { channels: [ { inputId: 0, outputId: 0 }, @@ -15,7 +12,9 @@ var CONFIG = { ], SETTLE_MS: 300, - CROSSTALK_MS: 200, + CROSSTALK_MS: 300, + + COUNT_SIGNAL: "btn_down", LONG_ENABLED: true, LONG_MIN_MS: 800, @@ -33,8 +32,6 @@ var CONFIG = { } }; -// === DEVICE INFO ============================================================= - var deviceInfo = Shelly.getDeviceInfo(); var deviceName = (deviceInfo.name && deviceInfo.name !== "") ? deviceInfo.name @@ -47,8 +44,6 @@ for (var ci = 0; ci < CONFIG.channels.length; ci++) { : "Channel " + (ci + 1); } -// === STATE =================================================================== - var chState = []; for (var si = 0; si < CONFIG.channels.length; si++) { chState.push({ @@ -65,8 +60,6 @@ for (var si = 0; si < CONFIG.channels.length; si++) { }); } -// === EVENT EMIT =============================================================== - function fireEvent(chIndex, logicalType, toggles) { var ch = CONFIG.channels[chIndex]; var eventType = CONFIG.names[logicalType] || logicalType; @@ -84,7 +77,6 @@ function fireEvent(chIndex, logicalType, toggles) { toggles: toggles }); - // Offline fallback if (logicalType === "single") { var w = Shelly.getComponentStatus("wifi"); if (w === null || w.sta_ip === null || w.sta_ip === "") { @@ -94,8 +86,6 @@ function fireEvent(chIndex, logicalType, toggles) { } } -// === EMERGENCY =============================================================== - function resetEmergency(chIndex) { var s = chState[chIndex]; s.emergencyCount = 0; @@ -109,6 +99,7 @@ function resetEmergency(chIndex) { function registerEmergency(chIndex, toggles) { var s = chState[chIndex]; + if (toggles < 1) return false; if (s.emergencyLocked) return true; @@ -142,11 +133,10 @@ function registerEmergency(chIndex, toggles) { return true; } + return false; } -// === TOGGLE HANDLING ========================================================== - function emitForToggles(chIndex, toggles) { if (registerEmergency(chIndex, toggles)) return; @@ -157,8 +147,6 @@ function emitForToggles(chIndex, toggles) { fireEvent(chIndex, type, toggles); } -// === BURST =================================================================== - function onBurstEnd(chIndex) { var s = chState[chIndex]; @@ -169,17 +157,19 @@ function onBurstEnd(chIndex) { var changes = s.stateChanges; s.stateChanges = 0; - var toggles = ((changes + 1) / 2) | 0; + // v3.5: one counted btn_down equals one physical toggle + var toggles = changes; if (toggles < 1) toggles = 1; print("[Burst] " + CONFIG.channels[chIndex].name + - ": " + JSON.stringify(changes) + " changes -> " + + ": " + JSON.stringify(changes) + " counted events -> " + JSON.stringify(toggles) + " toggles"); if (s.waitingForLong) { var elapsed = Date.now() - s.singleTime; s.waitingForLong = false; + if (s.longTimer !== null) { Timer.clear(s.longTimer); s.longTimer = null; @@ -193,7 +183,11 @@ function onBurstEnd(chIndex) { } fireEvent(chIndex, "single", 1); - if (toggles > 0) emitForToggles(chIndex, toggles); + + if (toggles > 0) { + emitForToggles(chIndex, toggles); + } + return; } @@ -206,28 +200,30 @@ function onBurstEnd(chIndex) { s.longTimer = Timer.set(CONFIG.LONG_MAX_MS, false, function() { s.waitingForLong = false; s.longTimer = null; + print("[Long] Timeout -> single"); emitForToggles(chIndex, 1); }); + return; } emitForToggles(chIndex, toggles); } -// === EVENT HANDLER =========================================================== - Shelly.addEventHandler(function(event) { if (event.component === undefined) return; if (event.info === undefined) return; var chIndex = -1; + for (var i = 0; i < CONFIG.channels.length; i++) { if (event.component === ("input:" + CONFIG.channels[i].inputId)) { chIndex = i; break; } } + if (chIndex === -1) return; var signal = null; @@ -249,9 +245,8 @@ Shelly.addEventHandler(function(event) { if (now - other.lastBurstEnd < CONFIG.CROSSTALK_MS) return; } - // Count only real toggle transitions - if (signal === "btn_down" || signal === "btn_up" || event.info.state !== undefined) { - + // Count only selected signal. Default: btn_down. + if (signal === CONFIG.COUNT_SIGNAL || event.info.state !== undefined) { s.stateChanges += 1; s.settling = true; @@ -270,7 +265,12 @@ Shelly.addEventHandler(function(event) { return; } - // Show native events for debugging + if (signal === "btn_up") { + print("[Ignored] " + CONFIG.channels[chIndex].name + + " = " + JSON.stringify(signal)); + return; + } + if (signal === "single_push" || signal === "double_push" || signal === "triple_push" || @@ -280,12 +280,11 @@ Shelly.addEventHandler(function(event) { } }); -// === INIT ==================================================================== - -print("=== Shelly Detached v3.4 ==="); +print("=== Shelly Detached v3.5 ==="); print("Device: " + deviceName); print("Timing: settle=" + JSON.stringify(CONFIG.SETTLE_MS) + "ms crosstalk=" + JSON.stringify(CONFIG.CROSSTALK_MS) + "ms"); +print("Counting only: " + CONFIG.COUNT_SIGNAL); print("Long: " + (CONFIG.LONG_ENABLED ? "enabled" : "disabled")); print("Emergency: " + CONFIG.EMERGENCY_COUNT + " toggles / " + CONFIG.EMERGENCY_WINDOW_MS + "ms");