1. Grundgedanke für dieses Script:
Eine automatische Tauchpumpe in einem Schacht zieht Wasser aus dem Boden, das bei starkem Regen von der Ringdrainage des Hauses abgeführt wird. Diese Pumpe hört und sieht man nicht! Und dass sie nicht arbeitet erkennt man daran, dass der Kellerboden eine Wasserschicht führt ... so wie zuletzt Weihnachten 2023 als die alte Pumpe kaputt war. Die neue Pumpe ist an Everhome angeschlossen und meldet per Nachricht aufs Handy wann sie läuft. Dazu hängt sie an einer Shelly Plus Plug. Gleichzeitig soll aber die LED auch leuchten wenn sie arbeitet (Strom zieht) zur optischen Kontrolle.
2. Das große Problem:
Die Shelly kennt nur zwei Zustände: ON und OFF. Für die Realisierung benötigen wir aber einen dritten Zustand: POWER. In der Regel ist die Dose ja eingeschaltet (ON), sie soll aber eine dritte Lichtfarbe zeigen, wenn die Pumpe läuft und Strom zieht. Dieser muss definiert werden als POWER = ON + (Energieverbrauch > Schwellwert). Der Schwellwert ist wichtig, da solche Geräte ja im Standby auch ein paar Watt ziehen. Ohne Schwellwert würde die LED immer POWER zeigen sobald man ein Gerät mit Stand-By-Verbrauch anschließt.
3. Versionen
- In der 1. Version habe ich genau das realisiert, aber irgendwie fand ich die fixe Farbe ein bisschen öde. Meistens ist die Dose ja ON, POWER ist nur selten und dann für vielleicht 30 Sekunden. OFF sollte nicht vorkommen, sonst besteht Überschwemmungsgefahr. Der Zustand soll also deutlich wahrnehmbar sein. Warum also nicht eine Möglichkeit einbauen eine Lichtanimation für jeden Zustand ablaufen zu lassen. Das habe ich
- in der 2. Version realisiert. Es stellte sich dann aber heraus, dass es hier einen grundlegenden Denkfehler gab. Es funktionierte zwar, aber nicht mit kurzen und sehr langen Leuchtphasen in einer Animation. Den habe ich dann
- in der 3. Version eliminiert, die ihr hier runterladen könnt.
4. Wie funktioniert das Script:
- Ihr müsst drei Arrays definieren: "onanimation", "offanimation" und "poweranimation". Dort legt ihr einzelne Lichtelemente hinein in der Form: [r, g, b, hell, dauer]. Bitte beachten: die drei Farben gehen von 0-100, nicht 255 wie üblich (API-Vorgabe). Die Helligkeit ist in %, die Dauer gibt an wie oft das Lichtelement wiederholt wird! Also 0 = 1x anzeigen, 99 = 99x wiederholen = 100x anzeigen! Ihr könnt ein einzelnes Lichtelement reinlegen, dann leuchtet die LED fix ("dauer" wird quasi ignoriert) oder eine ganze Lightshow programmieren, die so oft gespielt wird bis sich der Zustand der Dose ändert.
- Anschließend müsst ihr mit "timerinterval" einen Timer setzen. Ich habe festgestellt, dass 100 = 100ms das schnellste ist was der LED-Controller abkann. Die CPU rechnet viel schneller! Wenn ihr den Timer noch kürzer setzt besteht die Gefahr, dass die Lightshow unrhythmisch wird, weil der LED-Controller nicht mit dem Schalten der von der CPU angewiesenen Lichtfarbe nachkommt.
- Ausserdem müsst ihr noch den "threshold" (Schwellwert) in Watt setzen, oberhalb dessen der Zustand POWER geschaltet wird.
5. Was kann man noch damit machen?
Ich habe eine zweite Shelly so geschaltet, dass sie bei einem Solarüberschuss über 130W grün leuchtet und wenn man einen Verbraucher (Ladegerät Fahrradakku) anschließt pulsiert sie grün.
Ansonsten: denkt euch was aus, postet es hier. Ebenso eure goilen Lichtanimationen.
Viel Spaß
// JavaScript zur leistungsabhängigen LED-Beleuchtung einer Shelly Plus Plug mit Animationen
//
// Version 3
//
// Autor: Roland Mainka - Co-Autor: ChatGPT
const offanimation = [
[0, 0, 100, 10, 0], // Blau - 10% Helligkeit - 1 Zeiteinheit
[0, 0, 100, 100, 0] // Blau - 100% Helligkeit - 1 Zeiteinheit
]; //blaues Blinken
const onanimation = [
[50, 0, 0, 100, 10],
[51, 16, 16, 100, 10],
[55, 33, 23, 100, 10],
[60, 40, 46, 100, 10],
[60, 40, 66, 100, 10],
[50, 0, 50, 100, 10],
[40, 0, 61, 100, 10],
[28, 0, 88, 100, 10],
[2, 0, 82, 100, 10],
[0, 27, 86, 100, 10],
[0, 45, 89, 100, 10],
[0, 62, 91, 100, 10],
[4, 69, 64, 100, 10],
[9, 70, 30, 100, 10],
[0, 83, 11, 100, 10],
[0, 100, 0, 100, 10],
[50, 100, 0, 100, 10],
[78, 100, 0, 100, 10],
[100, 100, 0, 100, 10],
[100, 86, 0, 100, 10],
[100, 71, 0, 100, 10],
[100, 57, 0, 100, 10],
[100, 43, 0, 100, 10],
[100, 29, 0, 100, 10],
[100, 0, 0, 100, 10],
[100, 0, 50, 100, 10],
[100, 41, 71, 100, 10],
[100, 0, 100, 100, 10],
[66, 0, 73, 100, 10],
[0, 0, 0, 0, 10]
]; //Das Einhorn reitet über den Regenbogen
const poweranimation = [
[100, 0, 0, 10, 19], // Rot - 10% Helligkeit - 20 Zeiteinheiten
[100, 0, 0, 50, 0], // Rot - 50% Helligkeit - 1 Zeiteinheit
[100, 0, 0, 100, 4] // Rot - 100% Helligkeit - 10 Zeiteinheiten
]; //eine rote Animation, die einen Herzschlag nachahmen soll
const timerinterval = 100; // Intervall der Schleifendurchläufe
const threshold = 5; // Schwellenwert für den POWER-Zustand in Watt
// --- Ab hier Finger weg - es sei denn ihr kennt euch aus ---
let currentStatus = "";
let animation = [];
let currentElementIndex = 0;
let currentElementIteration = 0;
let apiCallInProgress = false;
function setAnimation(status) {
if (status === "OFF") {
animation = offanimation;
} else if (status === "ON") {
animation = onanimation;
} else if (status === "POWER") {
animation = poweranimation;
}
currentElementIndex = 0;
currentElementIteration = 0;
}
function setLedColor(color) {
if (apiCallInProgress) {
return;
}
apiCallInProgress = true;
let r = color[0];
let g = color[1];
let b = color[2];
let brightness = color[3];
Shelly.call("PLUGS_UI.SetConfig", {
id: 0,
config: {
leds: {
mode: "switch",
colors: {
"switch:0": {
on: {
rgb: [r, g, b],
brightness: brightness
},
off: {
rgb: [r, g, b],
brightness: brightness
}
}
}
}
}
}, function() {
apiCallInProgress = false;
});
}
function checkStatus(callback) {
Shelly.call("Switch.GetStatus", { id: 0 }, function(result) {
let power = result && result.hasOwnProperty('apower') ? result.apower : 0;
let newStatus = result && result.output ? (power > threshold ? "POWER" : "ON") : "OFF";
if (newStatus !== currentStatus) {
currentStatus = newStatus;
setAnimation(currentStatus);
}
callback();
});
}
function updateAnimation() {
checkStatus(function() {
const currentElement = animation[currentElementIndex];
if (currentElement) {
const durationFactor = currentElement[4];
setLedColor(currentElement);
if (currentElementIteration < durationFactor) {
currentElementIteration++;
} else {
currentElementIndex = (currentElementIndex + 1) % animation.length;
currentElementIteration = 0;
}
Timer.set(timerinterval, false, updateAnimation);
} else {
let errorMessage = "Fehler: currentElement ist undefiniert oder fehlerhaft.";
print(errorMessage);
}
});
}
updateAnimation();
Alles anzeigen