Die Übernahme erfolgte am 06. November, die Änderung der Domain, sowie das vollständige Rebranding Ende November. So wird es dann jetzt auch auf absehbare Zeit bleiben.
Beiträge von SoftCreatR
-
-
Das Benutzerkonto kann hier gelöscht werden: https://shelly-forum.com/account-management/
-
Ich hab den Code mal etwas geändert, da ich glaube, dass die Dinger mit der ES6-Syntax nicht ganz klar kommen.
-
Es ist noch früh, ich habe Hausbesetzer gelesen

Willkommen

-
Das wird es nicht geben.
-
-
SoftCreatR geht das technisch?
Ich bin eigentlich im Urlaub

-
Danke für den Code -- leider stoppt der mit 'ner Fehlermeldung:
Ah, die (ES6-)Syntax scheint bei Shelly-Scripts nicht zu funktionieren. Gut zu wissen
Ersetze in dem Script:durch:
-
Ich habe mir noch einmal die Definition des Begriffs "Kollaborateur" zu Gemüte geführt und mich dazu entschieden, diesen in "Schreiberling" abzuändern. Welche Trophäen es wofür gibt, siehst du hier: https://shelly-forum.com/trophy-list/
-
Ich habe mir das jetzt nochmal angesehen, vor allem die auskommentierten Teile. Ich habe mir einmal die Dokumentationen dazu angesehen:
- https://shelly-api-docs.shelly.cloud/gen2/Devices/G…ellyPlusRGBWPM/
- https://shelly-api-docs.shelly.cloud/gen2/Component…/Light#lightset
Demnach sollte sollte transition_duration grundsätzlich funktionieren. Aber kann es sein, dass der Shelly diese Option nicht so akzeptiert, wie Du es erwartest. Nicht jede Shelly-Version oder jedes Firmware-Update unterstützt alle Parameter wie transition_duration. Bei einigen Geräten oder Firmwares musst Du möglicherweise den Parameter anders nennen oder er wird gar nicht unterstützt. Das müsste man genauer "beleuchten".
Und zum eigentlichen Code: Ich habe mir mal die Mühe gemacht, diesen umzuschreiben, wie ich denke, dass es funktionieren könnte. Disclaimer: Ich hab kein Shelly-Gerät und kenne mich nicht mit der Programmierung selbiger aus. Meine Aussagen berufen sich auf meine Javascript-Kenntnisse, sowie die API-Dokumentation

Kurz und schmerzlos:
JavaScript
Alles anzeigen// Ampelsteuerung für Shelly Plus RGBW PM // =================================================== // // Ampel-Zustände: // 0 = alles aus // Gelb blinken: 101 (gelb ein), 102 (gelb aus, dann zurück zu 101) // Normale Ampel: 201...208 (Grün -> Gelb -> Rot -> Rot+Gelb) // Lauflicht: 301...308 (Rot -> Gelb -> Grün -> Rot ... zyklisch) // // Eingänge (Schalter) bestimmen, in welchem Modus die Ampel läuft: // Schalter-Kombinationen (summe der aktivierten Eingänge): // 0 = alles aus // 1 = Gelb blinkend // 2 = normale Ampel // 3 = Lauflicht // 4 = alles aus // // Die Eingänge werden einzeln abgefragt (S1...S4) und über einfache // Additionen zu einer "Schalter"-Variable kombiniert, um den Modus zu wählen. // ============================ // Konfiguration & Konstanten // ============================ const BRIGHTNESS = 15; // Standard-Helligkeit const LOOP_INTERVAL = 500; // Intervall für den Hauptloop (ms) // Zustände definieren (Konstanten für bessere Lesbarkeit) const STATES = { OFF: 0, YELLOW_BLINK_ON: 101, YELLOW_BLINK_OFF: 102, NORMAL_GREEN_START: 201, NORMAL_GREEN: 202, NORMAL_YELLOW_START: 203, NORMAL_YELLOW: 204, NORMAL_RED_START: 205, NORMAL_RED: 206, NORMAL_RED_YELLOW_START: 207, NORMAL_RED_YELLOW: 208, RUN_START: 301, RUN_WAIT_1: 302, RUN_SWITCH_YELLOW: 303, RUN_WAIT_2: 304, RUN_SWITCH_GREEN: 305, RUN_WAIT_3: 306, RUN_SWITCH_RED: 307, RUN_WAIT_4: 308, }; // Dauer der einzelnen Phasen (wie oft Loop durchlaufen wird, bis nächster Schritt) const TIMINGS = { NORMAL_GREEN: 6, NORMAL_YELLOW: 4, NORMAL_RED: 6, NORMAL_RED_YELLOW: 2, RUN_PHASE: 2, // Wartezeit für jede Lauflicht-Zwischenphase }; // ============================ // Globale Variablen // ============================ let Ampel = STATES.OFF; let LoopCount = 0; let oldSchalter = 10; // Startwert für Schalter, um initialen Wechsel zu erkennen // ============================ // Hilfsfunktionen // ============================ // Alle Kanäle ausschalten function AlleAus() { for (let i = 0; i < 4; i++) { Shelly.call("Light.set", { id: i, on: false, brightness: BRIGHTNESS }); } } // Eingänge (Schalter) auslesen und kombinierten Wert zurückgeben function readInputs() { const S1 = Shelly.getComponentStatus("input:0").state ? 1 : 0; const S2 = Shelly.getComponentStatus("input:1").state ? 2 : 0; const S3 = Shelly.getComponentStatus("input:2").state ? 3 : 0; const S4 = Shelly.getComponentStatus("input:3").state ? 4 : 0; // Summe bildet den "Schalter"-Wert return S1 + S2 + S3 + S4; } // Ampel-Wert anpassen, wenn sich der Schalterzustand ändert function updateAmpelFromInputs() { const Schalter = readInputs(); if (oldSchalter !== Schalter) { switch (Schalter) { case 0: Ampel = STATES.OFF; break; case 1: Ampel = STATES.YELLOW_BLINK_ON; break; case 2: Ampel = STATES.NORMAL_GREEN_START; break; case 3: Ampel = STATES.RUN_START; break; case 4: Ampel = STATES.OFF; break; default: Ampel = STATES.OFF; // Fallback, falls unerwarteter Wert break; } print(`Old: ${oldSchalter} Neu: ${Schalter} Ampel: ${Ampel} (${typeof Ampel})`); oldSchalter = Schalter; } } // Zustandslogik anwenden, abhängig von Ampel function applyState() { switch (Ampel) { case STATES.OFF: AlleAus(); break; // Gelb blinken case STATES.YELLOW_BLINK_ON: print("Blinklicht AN"); Shelly.call("Light.set", { id: 1, on: true }); Ampel = STATES.YELLOW_BLINK_OFF; break; case STATES.YELLOW_BLINK_OFF: Shelly.call("Light.setAll", { on: false }); Ampel = STATES.YELLOW_BLINK_ON; break; // Normale Ampel case STATES.NORMAL_GREEN_START: print("Normale Ampel: Grünphase starten"); Shelly.call("Light.set", { id: 2, on: true }); // Grün an Shelly.call("Light.set", { id: 1, on: false }); // Gelb aus Shelly.call("Light.set", { id: 0, on: false }); // Rot aus LoopCount = 0; Ampel = STATES.NORMAL_GREEN; break; case STATES.NORMAL_GREEN: LoopCount++; if (LoopCount > TIMINGS.NORMAL_GREEN) { Ampel = STATES.NORMAL_YELLOW_START; } break; case STATES.NORMAL_YELLOW_START: Shelly.call("Light.set", { id: 1, on: true }); // Gelb an Shelly.call("Light.set", { id: 2, on: false }); // Grün aus LoopCount = 0; Ampel = STATES.NORMAL_YELLOW; break; case STATES.NORMAL_YELLOW: LoopCount++; if (LoopCount > TIMINGS.NORMAL_YELLOW) { Ampel = STATES.NORMAL_RED_START; } break; case STATES.NORMAL_RED_START: Shelly.call("Light.set", { id: 0, on: true }); // Rot an Shelly.call("Light.set", { id: 1, on: false }); // Gelb aus LoopCount = 0; Ampel = STATES.NORMAL_RED; break; case STATES.NORMAL_RED: LoopCount++; if (LoopCount > TIMINGS.NORMAL_RED) { Ampel = STATES.NORMAL_RED_YELLOW_START; } break; case STATES.NORMAL_RED_YELLOW_START: LoopCount = 0; Shelly.call("Light.set", { id: 1, on: true }); // Gelb an Ampel = STATES.NORMAL_RED_YELLOW; break; case STATES.NORMAL_RED_YELLOW: LoopCount++; if (LoopCount > TIMINGS.NORMAL_RED_YELLOW) { Ampel = STATES.NORMAL_GREEN_START; // Zyklus von vorn (Grünphase) } break; // Lauflicht case STATES.RUN_START: print("Lauflicht starten"); AlleAus(); LoopCount = 0; Shelly.call("Light.set", { id: 0, on: true }); // Rot an Ampel = STATES.RUN_WAIT_1; break; case STATES.RUN_WAIT_1: LoopCount++; if (LoopCount > TIMINGS.RUN_PHASE) { Ampel = STATES.RUN_SWITCH_YELLOW; } break; case STATES.RUN_SWITCH_YELLOW: Shelly.call("Light.set", { id: 0, on: false }); Shelly.call("Light.set", { id: 1, on: true }); LoopCount = 0; Ampel = STATES.RUN_WAIT_2; break; case STATES.RUN_WAIT_2: LoopCount++; if (LoopCount > TIMINGS.RUN_PHASE) { Ampel = STATES.RUN_SWITCH_GREEN; } break; case STATES.RUN_SWITCH_GREEN: Shelly.call("Light.set", { id: 1, on: false }); Shelly.call("Light.set", { id: 2, on: true }); LoopCount = 0; Ampel = STATES.RUN_WAIT_3; break; case STATES.RUN_WAIT_3: LoopCount++; if (LoopCount > TIMINGS.RUN_PHASE) { Ampel = STATES.RUN_SWITCH_RED; } break; case STATES.RUN_SWITCH_RED: Shelly.call("Light.set", { id: 2, on: false }); Shelly.call("Light.set", { id: 0, on: true }); LoopCount = 0; Ampel = STATES.RUN_WAIT_4; break; case STATES.RUN_WAIT_4: LoopCount++; if (LoopCount > TIMINGS.RUN_PHASE) { Ampel = STATES.RUN_WAIT_1; // Zurück zum Start des Laufs (Endlos-Schleife) } break; default: // Unerwarteter Zustand: Sicherheitshalber alles aus und zurück auf OFF AlleAus(); Ampel = STATES.OFF; break; } } // Haupt-Schleifenfunktion, wird alle LOOP_INTERVAL ms aufgerufen function loop() { updateAmpelFromInputs(); applyState(); } // Initialisierung: alles aus AlleAus(); // Timer setzen für die Hauptschleife Timer.set(LOOP_INTERVAL, true, loop); -
Generell sollte Ampel nur ein einziges Mal definiert- und im nachfolgenden nur der Wert gesetzt werden. Denn wenn z.B. Schalter einen Zustand erreicht, der von dir nicht gehändelt wird, ist Ampel undefiniert, erst recht, weil es in deinem Switch/Case keinen Default gibt. Ist Schalter also z.B. NaN, oder größer als 5 bzw. kleiner als 0, ist Ampel zwangsläufig undefiniert.
Also:
JavaScriptlet Schalter = 1 * S1 + 2 * S2 + 3 * S3 + 4 * S4; let Ampel = 0; // Standardwert // .... Ampel = 123; // ... Ampel = 456;Andererseits hätte ich vermutlich noch eine Vielzahl von Optimierungen vorzuschlagen

Für Schalter bitte auch Punkt vor Strich beachten

-
Versuchs so:
JavaScript
Alles anzeigen// 🌡️ Skript zur einmaligen Anzeige der aktuellen Temperatur vom AM2301A Shelly.call( "HTTP.GET", { url: "http://127.0.0.1/rpc/Shelly.GetStatus" }, function(response, error_code, error_message) { if (error_code === 0) { let data = JSON.parse(response.body); // Abhängig von der Shelly-Firmware kann der Key unterschiedlich sein. // Bei Shelly Plus/Pro Geräten werden Sensoren meist als "sensor:0" benannt. let sensorData = data.status && data.status["sensor:0"]; if (sensorData && 'temperature' in sensorData) { let temperature = sensorData.temperature; print("🌡️ Aktuelle Temperatur: " + temperature + "°C"); } else { print("❌ Temperaturdaten nicht verfügbar."); } } else { print("❌ Fehler beim Abrufen der Temperatur: " + error_message); } } ); print("📢 Das Skript wurde erfolgreich ausgeführt."); -
Hat das tatsächlich schon mal jemand mit den oben angegebenen Quellen funktionieren umgesetzt?
Entweder ich bin blind, oder ein "HowTo" um ein Script von extern nachladen wird nicht aufgeführt.
Selbst ein js ex-/import funktioniert bei mir nicht...

Nach meinem Verständnis sind Script.Create, Script.PutCode und Script.Eval nicht dafür gedacht, von innerhalb eines laufenden Shelly-Skriptes zusätzlichen Code dynamisch zu laden. Sie dienen als externe Management- und Deployment-Tools über die RPC-Schnittstelle. Innerhalb eines Skriptes bleibt man meist auf den initial geladenen Code beschränkt.
Wie an anderer Stelle bereits erwähnt, hab ich von Shelly-Scripting keine Ahnung. Aber ich hab mir die Doku gerade kurz angesehen und hätte zumindest eine Idee, die man testen könnte:
JavaScript
Alles anzeigenconst externalJsUrl = "https://domain.de/script/test.js"; Shelly.call("HTTP.GET", { url: externalJsUrl }, function(result, error_code, error_message) { if (error_code === 0 && result && result.body) { try { eval(result.body); // Nach erfolgreichem eval können nun Funktionen/Variablen aus dem geladenen Code genutzt werden. Shelly.call("Sys.Log", { message: "Externer Code erfolgreich geladen und ausgeführt." }); } catch (e) { Shelly.call("Sys.Log", { message: `Fehler beim Ausführen des externen Codes: ${e}` }); } } else { Shelly.call("Sys.Log", { message: `Fehler beim Abrufen des externen Codes: ${error_msg}` }); } }); -
Bsp url: url
Das ist in der Form vollkommen legitim. Links steht der Parameter-Name, der übergeben wird und rechts der Wert dessen. Dass die Variable (für den Wert) denselben Namen hat, ist vielleicht etwas undienlich für die Lesbarkeit, aber nicht per se schlechter Programmierstil

Ich kenne mich mit Shelly-Scripting nicht aus, aber das ist in erster Linie ja Vanilla-Javascript, weshalb ich behaupte, dass das Problem die angegebene Webhook-URL ist, denn eine URL darf nur ein Fragezeichen für Parameter enthalten, beim Zusammensetzen wird aber ?humidity an die angegebene Webhook-URL gehangen, was im Ergebnis eine ungültige URL erzeugt.
Außerdem gibt es eine kleine Diskrepanz an dieser Stelle:
JavaScript// Überprüfen, ob die Feuchtigkeit über 40% gestiegen ist und höher als der vorherige Wert ist if (humidity > 35 && humidity > lastHumidity) { print(`🚀 Feuchtigkeit ist über 40% gestiegen! Sende Webhook...`); sendWebhook(humidity); }Denn sowohl im Kommentar, als auch in der ausgegebenen Nachricht steht 40%, geprüft wird aber auf > 35%. Das ist kein Fehler, aber halt auch nicht ganz korrekt

Eine korrekte Version des Scripts könnte z.B. so aussehen:
JavaScript
Alles anzeigen// ------------------------------- // 🌡️ Skript für Shelly Plus 1 mit AM2301A Addon // 🔥 Sendet Webhook, wenn die Feuchtigkeit > 40% steigt // ------------------------------- // Konfiguriere die URL deines Webhooks var webhookUrl = "http://192.168.178.89/api/v2/webhook_trigger?webhooks_key=OKVVRKIQLMHAVLDPIXSNENBECCXIBYWKNARVLOEFRUITPWIMVMORVFPJVFTVPWNJ&event=Keller"; // Aktueller Feuchtigkeitswert speichern, um nur bei Änderung zu reagieren var lastHumidity = null; // Event-Listener, der auf Sensor-Änderungen lauscht Shelly.addStatusHandler(function(event) { // Überprüfe, ob der Sensor-Status geändert wurde if (event.component === "sensor_0" && event.delta && ("humidity" in event.delta)) { var humidity = event.delta.humidity; // Neuer Feuchtigkeitswert print("💧 Neue Feuchtigkeit: " + humidity + "%"); // Überprüfen, ob die Feuchtigkeit über 40% gestiegen ist und höher als der vorherige Wert ist if (humidity > 40 && (lastHumidity === null || humidity > lastHumidity)) { print("🚀 Feuchtigkeit ist über 40% gestiegen! Sende Webhook..."); sendWebhook(humidity); } // Speichere den letzten Feuchtigkeitswert lastHumidity = humidity; } }); // Funktion zum Senden des Webhooks function sendWebhook(humidity) { var url = webhookUrl + (webhookUrl.indexOf("?") !== -1 ? "&" : "?") + "humidity=" + encodeURIComponent(humidity); Shelly.call( "HTTP.GET", { url: url }, function(response, error_code, error_message) { if (error_code === 0) { print("✅ Webhook erfolgreich gesendet: " + url); } else { print("❌ Fehler beim Senden des Webhooks: " + error_message); } } ); }Um zu verhindern, dass bei kleinen, schnellen Änderungen mehrfach Webhooks gesendet werden, kannst du ein einfaches Debouncing implementieren. Hier ein Beispiel:
JavaScript
Alles anzeigen// ------------------------------- // 🌡️ Skript für Shelly Plus 1 mit AM2301A Addon // 🔥 Sendet Webhook, wenn die Feuchtigkeit > 40% steigt // ------------------------------- // Konfiguriere die URL deines Webhooks var webhookUrl = "http://192.168.178.89/api/v2/webhook_trigger?webhooks_key=OKVVRKIQLMHAVLDPIXSNENBECCXIBYWKNARVLOEFRUITPWIMVMORVFPJVFTVPWNJ&event=Keller"; // Aktueller Feuchtigkeitswert speichern, um nur bei Änderung zu reagieren var lastHumidity = null; // Event-Listener, der auf Sensor-Änderungen lauscht Shelly.addStatusHandler(function(event) { // Überprüfe, ob der Sensor-Status geändert wurde if (event.component === "sensor_0" && event.delta && ("humidity" in event.delta)) { var humidity = event.delta.humidity; // Neuer Feuchtigkeitswert print("💧 Neue Feuchtigkeit: " + humidity + "%"); // Überprüfen, ob die Feuchtigkeit über 40% gestiegen ist und höher als der vorherige Wert ist if (humidity > 40 && (lastHumidity === null || humidity > lastHumidity)) { print("🚀 Feuchtigkeit ist über 40% gestiegen! Sende Webhook..."); sendWebhook(humidity); } // Speichere den letzten Feuchtigkeitswert lastHumidity = humidity; } }); var webhookTimeout = null; var debounceDelay = 30000; // 30 Sekunden function sendWebhook(humidity) { if (webhookTimeout !== null) { print("🚫 Webhook bereits gesendet. Warte auf das nächste Intervall."); return; } var url = webhookUrl + (webhookUrl.indexOf("?") !== -1 ? "&" : "?") + "humidity=" + encodeURIComponent(humidity); Shelly.call( "HTTP.GET", { url: url }, function(response, error_code, error_message) { if (error_code === 0) { print("✅ Webhook erfolgreich gesendet: " + url); // Setze das Timeout, um weitere Webhooks für die nächste Zeitspanne zu blockieren webhookTimeout = Timer.set(debounceDelay, false, function() { webhookTimeout = null; }); } else { print("❌ Fehler beim Senden des Webhooks: " + error_message); } } ); }Dieses Debouncing stellt sicher, dass nach dem Senden eines Webhooks eine bestimmte Zeit (z.B. 30 Sekunden) gewartet wird, bevor ein weiterer Webhook gesendet werden kann. Dies verhindert übermäßige Webhook-Aufrufe bei häufigen Feuchtigkeitsänderungen.
-
weil welcher Hacker will schon was von uns 0815 User?
Mal in deinen Spam-Ordner geguckt? Gelegenheit macht Diebe, egal ob 0815, oder 0900-User. Und wenn es bei dir nichts zu holen gibt, kann man dich auch noch anderweitig als Ressource nutzen (z.B. für DDos-Angriffe), wofür du am Ende haftbar gemacht werden kannst.
-
Naja, dass es die jetzt gibt heißt nicht, dass das Repertoire nicht noch erweitert wird.
-
Mir fehlt es als einiges. Die Frage ist, ob ich es will.
Etwas ernüchternd, wenn man innerhalb einer Stunde alles abgeräumt hat, was geht.
Hast du ja nicht 😊 Da die Trophäen gestern eingeführt wurden und gemäß ihrer Vergabebedingungen vergeben wurden, haben einige von euch halt binnen kürzester Zeit mehrere Trophäen erhalten.
-
Das sollte auf der Übersichtsseite ersichtlich sein 😅 Zwei-Faktor-Authentifizierung fehlt dir zum Beispiel noch.
-
Eine Auflistung erhältlicher Trophäen gibt es übrigens hier: https://shelly-forum.com/trophy-list/
Und hier könnt ihr festlegen, welche Trophäen bei euch angezeigt werden sollen: https://shelly-forum.com/settings/
-
wo kann ich das in € umtauschen?


Das ist Katzengold, dafür bekommst du nicht einmal 100 Rubel.