Last active
March 7, 2026 09:24
-
-
Save Eetezadi/c539d15fa4648856c2732a71ef0a4e25 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// <reference path="../../shelly-script.d.ts" /> | |
| // <reference path="../../shelly-script.d.ts" /> | |
| // Shelly Script: Router Watchdog | |
| // Monitors internet connectivity and resets router by cycling power when needed | |
| let CONFIG = { | |
| endpoints: [ | |
| "https://global.gcping.com/ping", | |
| "https://www.switch.ch", | |
| ], | |
| numberOfFails: 3, // failures before reset | |
| httpTimeout: 10, // seconds before request timeout | |
| toggleTime: 30, // seconds to keep relay off | |
| pingTime: 180, // seconds between connectivity checks | |
| maxBackoffTime: 21600, // max backoff (6 hours) | |
| initialBackoffTime: 300, // initial backoff (5 minutes) | |
| backoffMultiplier: 2, // backoff multiplier | |
| }; | |
| let endpointIdx = 0; | |
| let failCounter = 0; | |
| let pingTimer = null; | |
| let resetCounter = 0; | |
| let currentBackoffTime = 0; | |
| /** | |
| * Reset router with exponential backoff for persistent failures | |
| */ | |
| function resetRouter() { | |
| print("Too many fails, resetting..."); | |
| failCounter = 0; | |
| resetCounter++; | |
| Timer.clear(pingTimer); | |
| // Apply backoff after first reset | |
| if (resetCounter > 1) { | |
| if (currentBackoffTime === 0) { | |
| currentBackoffTime = CONFIG.initialBackoffTime; | |
| } else { | |
| // Increase backoff time exponentially with cap | |
| currentBackoffTime = currentBackoffTime * CONFIG.backoffMultiplier; | |
| if (currentBackoffTime > CONFIG.maxBackoffTime) { | |
| currentBackoffTime = CONFIG.maxBackoffTime; | |
| } | |
| } | |
| print("Backoff active: " + currentBackoffTime + " seconds before next check"); | |
| } | |
| // Turn off switch and toggle back after delay | |
| Shelly.call( | |
| "Switch.Set", | |
| { id: 0, on: false, toggle_after: CONFIG.toggleTime }, | |
| function () {} | |
| ); | |
| } | |
| /** | |
| * Start timer for connectivity checks | |
| */ | |
| function startPingTimer() { | |
| pingTimer = Timer.set(CONFIG.pingTime * 1000, true, pingEndpoints); | |
| } | |
| function pingEndpoints() { | |
| Shelly.call( | |
| "http.get", | |
| { url: CONFIG.endpoints[endpointIdx], timeout: CONFIG.httpTimeout }, | |
| function (response, error_code, error_message) { | |
| //http timeout, magic number, not yet documented | |
| if (error_code === -114 || error_code === -104) { | |
| print("Failed to fetch ", CONFIG.endpoints[endpointIdx]); | |
| failCounter++; | |
| print("Number of fails:", failCounter); | |
| print("Checking next endpoint in " + CONFIG.pingTime + " seconds"); | |
| endpointIdx++; | |
| endpointIdx = endpointIdx % CONFIG.endpoints.length; | |
| } else { | |
| print("We are online :)"); | |
| failCounter = 0; | |
| // Reset backoff on successful connection | |
| resetCounter = 0; | |
| currentBackoffTime = 0; | |
| } | |
| if (failCounter >= CONFIG.numberOfFails) { | |
| resetRouter(); | |
| return; | |
| } | |
| } | |
| ); | |
| } | |
| print("Starting watchdog timer..."); | |
| startPingTimer(); | |
| // Handle router restart completion | |
| Shelly.addStatusHandler(function (status) { | |
| // Only process switch events from timer for our switch | |
| if (status.name !== "switch" || | |
| status.id !== 0 || | |
| typeof status.delta.source === "undefined" || | |
| status.delta.source !== "timer" || | |
| status.delta.output !== true) return; | |
| // Apply backoff if needed or restart immediately | |
| if (currentBackoffTime > 0) { | |
| print("Applying backoff: " + currentBackoffTime + " seconds"); | |
| Timer.set(currentBackoffTime * 1000, false, function() { | |
| print("Backoff complete, resuming checks"); | |
| startPingTimer(); | |
| }); | |
| } else { | |
| startPingTimer(); | |
| } | |
| }); |
Author
Hi, frankly I abandoned the project. Unit kept crashing.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for the very useful script. Though, I have a router that I reboot weekly and it takes roughly 2 minutes to reconnect to the internet. With the current version of your script, the Shelly plug reboots a few times before the router has long enough to reconnect. How could I handle this? Maybe a delay at the beginning of the script? Thank you in advance.