From 29785a96bc58bad7159ed741f6beb8ac720c37a1 Mon Sep 17 00:00:00 2001 From: Peter Siegmund Date: Thu, 1 Jan 2026 17:52:02 +0100 Subject: [PATCH] add thunder configuration Signed-off-by: Peter Siegmund --- firmware/README-API.md | 42 ++++++++++++--- firmware/storage/www/index.html | 8 ++- firmware/storage/www/js/app.js | 1 + firmware/storage/www/js/i18n.js | 4 +- firmware/storage/www/js/light.js | 89 ++++++++++++++++++++++++++++++++ 5 files changed, 135 insertions(+), 9 deletions(-) diff --git a/firmware/README-API.md b/firmware/README-API.md index f5c6ab1..d2f3afb 100644 --- a/firmware/README-API.md +++ b/firmware/README-API.md @@ -154,6 +154,34 @@ Turns the main light on or off. --- +#### Set Thunder Effect + +Turns the thunder/lightning effect on or off. + +- **URL:** `/api/light/thunder` +- **Method:** `POST` +- **Content-Type:** `application/json` +- **Request Body:** + +```json +{ + "on": true +} +``` + +| Field | Type | Required | Description | +|-------|---------|----------|--------------------------------| +| on | boolean | Yes | `true` = on, `false` = off | + +- **Response:** `200 OK` on success + +**Notes:** +- When enabled, random lightning flashes are triggered +- Can be combined with any light mode +- Thunder effect stops automatically when light is turned off + +--- + #### Set Light Mode Sets the lighting mode. @@ -211,6 +239,7 @@ Returns current light status (alternative to WebSocket). ```json { "on": true, + "thunder": false, "mode": "simulation", "schema": "schema_01.csv", "color": { @@ -221,12 +250,13 @@ Returns current light status (alternative to WebSocket). } ``` -| Field | Type | Description | -|--------|---------|--------------------------------------| -| on | boolean | Current power state | -| mode | string | Current mode (day/night/simulation) | -| schema | string | Active schema filename | -| color | object | Current RGB color being displayed | +| Field | Type | Description | +|---------|---------|--------------------------------------| +| on | boolean | Current power state | +| thunder | boolean | Current thunder effect state | +| mode | string | Current mode (day/night/simulation) | +| schema | string | Active schema filename | +| color | object | Current RGB color being displayed | --- diff --git a/firmware/storage/www/index.html b/firmware/storage/www/index.html index 85415bd..74e8b04 100644 --- a/firmware/storage/www/index.html +++ b/firmware/storage/www/index.html @@ -40,7 +40,6 @@

Lichtsteuerung

-

Ein/Aus

Licht @@ -49,6 +48,13 @@ 💡
+
+ Gewitter + +
diff --git a/firmware/storage/www/js/app.js b/firmware/storage/www/js/app.js index 7a81dc7..6e76058 100644 --- a/firmware/storage/www/js/app.js +++ b/firmware/storage/www/js/app.js @@ -47,6 +47,7 @@ document.addEventListener('DOMContentLoaded', async () => { await initCapabilities(); initWebSocket(); updateConnectionStatus(); + loadLightStatus(); // Only load scenes and devices if thread is enabled if (isThreadEnabled()) { diff --git a/firmware/storage/www/js/i18n.js b/firmware/storage/www/js/i18n.js index 9e9b936..072c707 100644 --- a/firmware/storage/www/js/i18n.js +++ b/firmware/storage/www/js/i18n.js @@ -33,8 +33,8 @@ const translations = { // Light Control 'control.light.title': 'Lichtsteuerung', - 'control.light.onoff': 'Ein/Aus', 'control.light.light': 'Licht', + 'control.light.thunder': 'Gewitter', 'control.mode.title': 'Betriebsmodus', 'control.schema.active': 'Aktives Schema', 'control.status.title': 'Aktueller Status', @@ -204,8 +204,8 @@ const translations = { // Light Control 'control.light.title': 'Light Control', - 'control.light.onoff': 'On/Off', 'control.light.light': 'Light', + 'control.light.thunder': 'Thunder', 'control.mode.title': 'Operating Mode', 'control.schema.active': 'Active Schema', 'control.status.title': 'Current Status', diff --git a/firmware/storage/www/js/light.js b/firmware/storage/www/js/light.js index 3cbcf0b..3983f08 100644 --- a/firmware/storage/www/js/light.js +++ b/firmware/storage/www/js/light.js @@ -1,4 +1,6 @@ // Light control +let thunderOn = false; + async function toggleLight() { lightOn = !lightOn; updateLightToggle(); @@ -36,6 +38,44 @@ function updateLightToggle() { } } +// Thunder control +async function toggleThunder() { + thunderOn = !thunderOn; + updateThunderToggle(); + + try { + const response = await fetch('/api/light/thunder', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ on: thunderOn }) + }); + + if (response.ok) { + showStatus('light-status', `${t('control.light.thunder')} ${thunderOn ? t('common.on') : t('common.off')}`, 'success'); + } else { + throw new Error(t('error')); + } + } catch (error) { + showStatus('light-status', `Demo: ${t('control.light.thunder')} ${thunderOn ? t('common.on') : t('common.off')}`, 'success'); + } +} + +function updateThunderToggle() { + const toggle = document.getElementById('thunder-toggle'); + const state = document.getElementById('thunder-state'); + const icon = document.getElementById('thunder-icon'); + + if (thunderOn) { + toggle.classList.add('active'); + state.textContent = t('common.on'); + icon.textContent = '⛈️'; + } else { + toggle.classList.remove('active'); + state.textContent = t('common.off'); + icon.textContent = '⚡'; + } +} + // Mode control async function setMode(mode) { currentMode = mode; @@ -100,3 +140,52 @@ async function setActiveSchema() { document.getElementById('current-schema').textContent = schemaName; } } + +/** + * Load light status from server + */ +async function loadLightStatus() { + try { + const response = await fetch('/api/light/status'); + if (response.ok) { + const status = await response.json(); + + // Update light state + if (typeof status.on === 'boolean') { + lightOn = status.on; + updateLightToggle(); + } + + // Update thunder state + if (typeof status.thunder === 'boolean') { + thunderOn = status.thunder; + updateThunderToggle(); + } + + // Update mode + if (status.mode) { + currentMode = status.mode; + updateModeButtons(); + updateSimulationOptions(); + document.getElementById('current-mode').textContent = t(`mode.${status.mode}`); + } + + // Update schema + if (status.schema) { + document.getElementById('active-schema').value = status.schema; + const schemaNum = status.schema.replace('schema_0', '').replace('.csv', ''); + document.getElementById('current-schema').textContent = t(`schema.name.${schemaNum}`); + } + + // Update current color + if (status.color) { + const colorPreview = document.getElementById('current-color'); + if (colorPreview) { + colorPreview.style.backgroundColor = `rgb(${status.color.r}, ${status.color.g}, ${status.color.b})`; + } + } + } + } catch (error) { + console.log('Light status not available'); + } +}