Script Shelly scripts
Phone alert when your mains voltage goes too high or too low
Reads the supply voltage on a Shelly energy meter and sends a notification to your phone through ntfy when it stays outside the Australian range, then again when it's back.
- Gen3
- Gen4
- Pro
// Mains voltage alert: tells your phone through ntfy when the supply voltage stays// outside the Australian range, and again when it's back. Needs a Shelly energy meter. let CONFIG = { highVolts: 253, lowVolts: 216, holdSec: 60, ntfyTopic: "", meterId: 0,}; // Read the meter every 5 seconds, so a short spike is seen without filling the log.let READ_EVERY_SEC = 5;// The voltage has to come this far back inside the range before the all-clear,// so a reading that sits right on the limit can't send alert after alert.let RECOVER_VOLTS = 2;// Unsent messages are kept and retried after each reading, up to this many.let MAX_QUEUED = 10; let outSince = 0;let alerted = false;let worst = 0;let queue = [];let sending = false;let warnedNoMeter = false; function readVolts() { let s = Shelly.getComponentStatus("em1", CONFIG.meterId); if (s === null || typeof s.voltage !== "number") return null; return s.voltage;} function onSent(res, err) { sending = false; if (err === 0 && res.code === 200) { queue.splice(0, 1); sendNext(); } else { print("Couldn't reach ntfy. Will try again shortly."); }} function sendNext() { if (sending || queue.length === 0 || CONFIG.ntfyTopic === "") return; sending = true; Shelly.call("HTTP.Request", { method: "POST", url: "https://ntfy.sh/" + CONFIG.ntfyTopic, body: queue[0], headers: { "Content-Type": "text/plain" }, timeout: 15, }, onSent);} function alert(msg) { print(msg); if (queue.length >= MAX_QUEUED) queue.splice(0, 1); queue.push(msg);} function isWorse(v) { if (worst === 0) return true; if (v > CONFIG.highVolts) return v > worst; return v < worst;} function check() { let v = readVolts(); if (v === null) { if (!warnedNoMeter) print("No voltage reading. Check meterId."); warnedNoMeter = true; return; } warnedNoMeter = false; let now = Shelly.getComponentStatus("sys").uptime; let out = v > CONFIG.highVolts || v < CONFIG.lowVolts; let recovered = v <= CONFIG.highVolts - RECOVER_VOLTS && v >= CONFIG.lowVolts + RECOVER_VOLTS; if (out) { if (outSince === 0) { outSince = now; worst = 0; print("Voltage " + v.toFixed(1) + " V is outside " + CONFIG.lowVolts + "-" + CONFIG.highVolts + " V. Watching."); } if (isWorse(v)) worst = v; if (!alerted && now - outSince >= CONFIG.holdSec) { alerted = true; alert("Mains voltage is " + (v > CONFIG.highVolts ? "high" : "low") + ": " + v.toFixed(1) + " V for over " + CONFIG.holdSec + " s (range " + CONFIG.lowVolts + "-" + CONFIG.highVolts + " V)."); } } else if (outSince !== 0 && (recovered || !alerted)) { if (alerted) { let secs = now - outSince; let took = secs < 60 ? "under a minute" : "about " + Math.round(secs / 60) + " min"; alert("Mains voltage is back to " + v.toFixed(1) + " V after " + took + ". It reached " + worst.toFixed(1) + " V."); } else { print("Voltage back to " + v.toFixed(1) + " V before the hold time. No alert."); } outSince = 0; alerted = false; } sendNext();} Timer.set(READ_EVERY_SEC * 1000, true, check);print("Voltage alert started. Range " + CONFIG.lowVolts + "-" + CONFIG.highVolts + " V, alert after " + CONFIG.holdSec + " s outside it.");check(); What it does
Every 5 seconds the script reads the voltage from your meter. If it stays above 253 V or below 216 V for a minute, your phone gets an alert with the reading. When the voltage comes back inside the range, a second message says how long it lasted and how far it went. A reading that crosses the line and comes straight back is printed in the console but doesn't alert you.
High voltage is common on streets with a lot of rooftop solar, and it can make a solar inverter switch itself off. A record of when it happens is useful if you report it to your electricity distributor. The meter reads to within 1%, so a reading of 255 V could be anywhere from about 252 V to 258 V. If ntfy can't be reached, the alert waits on the Shelly and goes out once it can.
Install it on your Shelly
Before you install
- Subscribe in ntfy
Install the ntfy app and subscribe to a topic name nobody would guess, such as smith-volts-4821.
Install the script
Install it on the meter.
Shelly Smart Control
- Open the device and tap Scripts
In Shelly Smart Control, open the room, then the device. Tap Scripts, the { } icon in the menu down the left.
- Tap Create new script
If the device has no scripts yet, the screen says No scripts created.
- Name it, paste the code, then tap Save
Name it mains-voltage-alert. Tap in the code area, paste the script you copied above, then tap Save (the disk icon at the top right).
- Tap the play button
The play button lights up once the script is saved. Tap it and a message says the script has been started.
- Close the editor and turn on Run on startup
Back on the Scripts screen, turn on Run on startup next to your script, so it starts again after a power cut or a firmware update.
Direct access via IP
- Open the device's web page and click Scripts
Find the IP address in the Shelly app under Device settings, then Device information, and type it into a browser on the same Wi-Fi. Click Scripts in the menu on the left.
- Click Create script
If the device has no scripts yet, the list says so.
- Name it, paste the code, then click Save
Name it mains-voltage-alert. Click in the code area, paste the script you copied above, then click Save (the disk icon above the code).
- Click Run and check the console
Run appears once the script is saved. The console under the code then prints what the script is doing.
- Turn on Run on startup
Click Scripts again and turn on Run on startup next to your script, so it starts again after a power cut or a firmware update.
After you install
- Test it
On the meter's web page, the console prints Voltage alert started with your range. To see an alert, stop the script, set highVolts a few volts under the voltage the meter shows, save it and run it again, then wait out the hold time. Set it back afterwards.
Changelog
v1.0 First release. Still need a hand?
We answer most messages within one business day. If your question is about an existing order, have your order number ready. It speeds things up.
Contact us