Last active
February 5, 2025 19:41
-
-
Save ThiefMaster/9d2c2f30b9998e3b27b4271bd56aa9b1 to your computer and use it in GitHub Desktop.
This script can be used on a Shelly 2PM (gen3) to nicely control a french heater that's using the "fil pilote" protocol.
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
const CONFIG = { | |
// ID of the virtual component to select the mode | |
componentId: 200, | |
// ID of the relay with the diode providing a negative wave | |
negativeWaveSwitch: 0, | |
// ID of the relay with the diode providing a positive wave | |
positiveWaveSwitch: 1, | |
}; | |
const simpleModes = { | |
comfort: [false, false], | |
eco: [true, true], | |
antifrost: [true, false], | |
off: [false, true], | |
}; | |
const timerDurations = { | |
comfort_minus1: 3, | |
comfort_minus2: 7, | |
}; | |
CONFIG.componentName = 'enum:' + CONFIG.componentId; | |
let currentMode = null; | |
let timer = null; | |
Shelly.call('Enum.GetStatus', {id: CONFIG.componentId}, function (res) { | |
print('Initial mode', res.value); | |
currentMode = res.value; | |
handleModeChange(); | |
}); | |
Shelly.addStatusHandler(function (evt) { | |
if (evt.component !== CONFIG.componentName) { return; } | |
print('New mode', evt.delta.value); | |
currentMode = evt.delta.value; | |
handleModeChange(); | |
}); | |
function setOutput(a, b) { | |
Shelly.call('Switch.set', {id: CONFIG.negativeWaveSwitch, on: a}); | |
Shelly.call('Switch.set', {id: CONFIG.positiveWaveSwitch, on: b}); | |
} | |
function handleModeChange() { | |
print('Mode changed to', currentMode); | |
if (timer !== null) { | |
print('Clearing timer'); | |
Timer.clear(timer); | |
timer = null; | |
} | |
const simple = simpleModes[currentMode]; | |
const duration = timerDurations[currentMode]; | |
if (simple) { | |
print('Simple mode -> updating relays:', simple); | |
setOutput.apply(null, simple); | |
} else if (duration) { | |
print('Time-based mode -> starting timer:', duration); | |
timedCycle(duration); | |
} else { | |
print('Invalid mode', currentMode); | |
} | |
} | |
function timedCycle(duration) { | |
const onDuration = duration * 1000; | |
const offDuration = 300000 - onDuration; | |
print('Starting ON cycle', duration); | |
setOutput(true, true); | |
timer = Timer.set(onDuration, false, function () { | |
print('Starting OFF cycle', offDuration / 1000); | |
setOutput(false, false); | |
timer = Timer.set(offDuration, false, timedCycle, duration); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment