let Switch = name: topic: { title = name; type = "switch"; icon = "icons/power_button.png"; topic.get = topic; topic.set = "${topic}/set"; transform.get = "return (message.state == 'ON') ? true : false"; transform.set = "return JSON.stringify({state: (input) ? 'ON' : 'OFF'})"; }; BrighnessSlider = name: topic: { title = name; type = "slider"; icon = "icons/bulb.png"; sliderMinValue = 0; sliderMaxValue = 254; sliderStepValue = 1; topic.get = topic; topic.set = "${topic}/set"; transform.get = "return message.brightness"; transform.set = "return JSON.stringify({brightness: Number(input)})"; }; ColorTemperatureSlider = name: topic: { title = name; type = "slider"; icon = "icons/bulb.png"; sliderMinValue = 250; sliderMaxValue = 454; sliderStepValue = 1; topic.get = topic; topic.set = "${topic}/set"; transform.get = "return message.color_temp"; transform.set = "return JSON.stringify({color_temp: Number(input)})"; }; DimmableLamp = name: topic: { title = name; items = [ (Switch "Power" topic) (BrighnessSlider "Brighness" topic) ]; }; WhiteSpectrumLamp = name: topic: { title = name; items = [ (Switch "Power" topic) (BrighnessSlider "Brighness" topic) (ColorTemperatureSlider "Color Temperature" topic) ]; }; ColorSpectrumLamp = name: topic: { title = name; items = [ (Switch "Power" topic) (BrighnessSlider "Brighness" topic) (ColorTemperatureSlider "Color Temperature" topic) { title = "Color"; type = "select"; icon = "icons/bulb.png"; topic.get = topic; topic.set = "${topic}/set"; transform.get = "return message.color.x + ','+message.color.y"; transform.set = "return JSON.stringify({color: {x: input.split(',')[0], y: input.split(',')[1]}})"; selectOptions = [ { label = "Red"; value = "0.71,0.26"; } { label = "Green"; value = "0.19,0.78"; } { label = "Blue"; value = "0.09,0.13"; } ]; } ]; }; in { appName = "Smart-Home"; extraCSS = "/extra.css"; pages = [ { id = "mainpage"; icon = "favicon-512x512.png"; title = "Smart-Home"; sections = [ (WhiteSpectrumLamp "Hallway" "zigbee2mqtt/ikea_lamp_hallway") (WhiteSpectrumLamp "Living room" "zigbee2mqtt/ikea_lamp_livingroom") (WhiteSpectrumLamp "Sleeping room" "zigbee2mqtt/ikea_lamp_sleepingroom") (DimmableLamp "Desk" "zigbee2mqtt/tuya_led_stripe_desk") (ColorSpectrumLamp "RGB Lamp" "zigbee2mqtt/ikea_lamp_rgb") { title = "Temperature-Sensors"; items = [ { title = "Fridge"; type = "text"; topic = "zigbee2mqtt/tuya_sensor_fridge"; icon = "icons/temperature.png"; transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'"; } { title = "Bathroom"; type = "text"; topic = "zigbee2mqtt/tuya_sensor_bathroom"; icon = "icons/temperature.png"; transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'"; } { title = "Door"; type = "text"; topic = "zigbee2mqtt/tuya_sensor_l"; icon = "icons/temperature.png"; transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'"; } { title = "Bed"; type = "text"; topic = "zigbee2mqtt/tuya_sensor_l2"; icon = "icons/temperature.png"; transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'"; } ]; } { items = [ { title = "Departures"; type = "text"; icon = "icons/electric_range.png"; link = "#departures"; } { title = "Grafana-Dashboard"; type = "text"; icon = "icons/sun.png"; link = "https://grafana.ctu.cx/d/FRDYqjEGz/smarthome-influx?orgId=1&refresh=5s"; } ]; } ]; } { id = "departures"; title = "Departures"; sections = [ { items = [ { type = "html"; topic = "departures2mqtt"; html = "
"; transform = '' clearInterval(globalThis.departuresUpdater) globalThis.departuresUpdater = setInterval(() => { let element = document.querySelector('[data-last-updated]'); element.textContent = 'Last Update: ' + (Math.floor(Date.now() / 1000) - element.dataset.lastUpdated) + ' seconds ago'; }, 10000) let output = ""; Object.entries(message.departures).forEach((data) => { output += '
' + data[0] + '
'; output += '
Linie
'; data[1].forEach((departure) => output += '
' + departure.line + '
'); output += '
'; output += '
Richtung
'; data[1].forEach((departure) => output += '
' + departure.direction + '
'); output += '
'; output += '
Abfahrt
'; data[1].forEach((departure) => output += '
' + (Number(departure.departure_in) ? departure.departure_in + " min" : "sofort") + '
'); output += '
'; output += '
'; }); output += '
Last Update: ' + (Math.floor(Date.now() / 1000) - message.lastUpdated) + ' seconds ago
'; return output; ''; } ]; } ]; } ]; }