diff --git a/.storage/lovelace.ender5_printer b/.storage/lovelace.ender5_printer index 1c320a4d..806a2122 100644 --- a/.storage/lovelace.ender5_printer +++ b/.storage/lovelace.ender5_printer @@ -8,33 +8,37 @@ { "title": "Ender 5", "path": "printer", + "icon": "mdi:printer-3d-nozzle", "type": "sections", "max_columns": 3, - "badges": [ - { - "type": "entity", - "entity": "sensor.octoprint_print_status" - } - ], + "subview": false, "sections": [ { "type": "grid", "cards": [ { "type": "heading", - "heading": "Controls", - "heading_style": "title" - }, - { - "type": "horizontal-stack", - "cards": [ + "icon": "mdi:printer", + "heading_style": "title", + "heading": "Ender 5", + "badges": [ + { + "type": "entity", + "show_state": true, + "show_icon": false, + "entity": "sensor.octoprint_print_status" + }, { "type": "button", - "entity": "switch.octoprint_pause_print", - "name": "Pause", "icon": "mdi:pause", + "text": "Pause", + "color": "", "tap_action": { - "action": "toggle" + "action": "perform-action", + "perform_action": "switch.turn_on", + "target": { + "entity_id": "switch.octoprint_pause_print" + } }, "visibility": [ { @@ -51,11 +55,15 @@ }, { "type": "button", - "entity": "switch.octoprint_pause_print", - "name": "Resume", "icon": "mdi:play", + "text": "Resume", + "color": "", "tap_action": { - "action": "toggle" + "action": "perform-action", + "perform_action": "switch.turn_off", + "target": { + "entity_id": "switch.octoprint_pause_print" + } }, "visibility": [ { @@ -67,9 +75,9 @@ }, { "type": "button", - "entity": "button.octoprint_cancel_print", - "name": "Cancel", - "icon": "mdi:stop-circle-outline", + "icon": "mdi:stop", + "text": "Cancel", + "color": "#F44336", "tap_action": { "action": "perform-action", "perform_action": "button.press", @@ -89,295 +97,420 @@ ] }, { - "type": "vertical-stack", - "cards": [ - { - "type": "button", - "entity": "switch.octoprint_connect_to_printer", - "name": "Connect", - "icon": "mdi:lan-connect", - "show_state": false, - "tap_action": { - "action": "toggle" - }, - "visibility": [ - { - "condition": "state", - "entity": "binary_sensor.octoprint_connected", - "state": "off" - } - ] + "type": "button", + "icon": "mdi:alert-octagon", + "text": "Emergency stop", + "color": "#F44336", + "tap_action": { + "action": "perform-action", + "perform_action": "button.press", + "target": { + "entity_id": "button.octoprint_emergency_stop" }, - { - "type": "button", - "entity": "switch.octoprint_connect_to_printer", - "name": "Disconnect", - "icon": "mdi:lan-disconnect", - "show_state": false, - "tap_action": { - "action": "toggle" - }, - "visibility": [ - { - "condition": "state", - "entity": "binary_sensor.octoprint_connected", - "state": "on" - } - ] + "confirmation": { + "text": "Emergency stop the printer NOW?" } - ] + } } ] }, { - "type": "button", - "entity": "button.octoprint_emergency_stop", - "name": "EMERGENCY STOP", - "icon": "mdi:alert-octagon", - "tap_action": { - "action": "perform-action", - "perform_action": "button.press", - "target": { - "entity_id": "button.octoprint_emergency_stop" - }, - "confirmation": { - "text": "Emergency stop the printer now?" - } - } - }, - { - "type": "grid", - "columns": 2, - "square": false, + "type": "horizontal-stack", "cards": [ { "type": "custom:button-card", - "entity": "sensor.octoprint_print_status", - "name": "Nozzle", - "icon": "mdi:thermometer-lines", - "label": "[[[ return states['sensor.octoprint_tool_0_temperature'].state + '° / ' + states['sensor.octoprint_tool_0_target'].state + '°'; ]]]", - "color": "#E53935", + "entity": "sensor.octoprint_tool_0_temperature", + "show_name": false, + "show_state": false, + "show_icon": false, + "tap_action": { + "action": "more-info" + }, + "custom_fields": { + "content": "[[[\n const sec = 'var(--secondary-text-color)';\n const pri = 'var(--primary-text-color)';\n return `\n
\n
\n \n Nozzle\n
\n ${Math.round(parseFloat(states['sensor.octoprint_tool_0_temperature']?.state) || 0) + '\\u00B0C / target ' + Math.round(parseFloat(states['sensor.octoprint_tool_0_target']?.state) || 0) + '\\u00B0C'}\n
\n `;\n]]]" + }, "styles": { "card": [ { - "height": "74px", - "padding": "6px 10px" + "background": "var(--ha-card-background, var(--card-background-color))" + }, + { + "border-radius": "12px" + }, + { + "padding": "0" + }, + { + "height": "74px" + }, + { + "position": "relative" + }, + { + "box-shadow": "none" + }, + { + "border": "1px solid rgba(var(--rgb-primary-text-color), 0.08)" } ], - "name": [ - { - "font-size": "12px", - "justify-self": "start", - "opacity": "0.8" - } - ], - "icon": [ - { - "color": "#E53935", - "width": "26px" - } - ], - "label": [ - { - "font-size": "17px", - "font-weight": "600", - "justify-self": "start", - "color": "#E53935" - } - ] + "custom_fields": { + "content": [ + { + "position": "absolute" + }, + { + "inset": "0" + }, + { + "padding": "0" + } + ] + } } }, { "type": "custom:button-card", - "entity": "sensor.octoprint_print_status", - "name": "Bed", - "icon": "mdi:radiator", - "label": "[[[ return states['sensor.octoprint_bed_temperature'].state + '° / ' + states['sensor.octoprint_bed_target'].state + '°'; ]]]", - "color": "#FB8C00", + "entity": "sensor.octoprint_bed_temperature", + "show_name": false, + "show_state": false, + "show_icon": false, + "tap_action": { + "action": "more-info" + }, + "custom_fields": { + "content": "[[[\n const sec = 'var(--secondary-text-color)';\n const pri = 'var(--primary-text-color)';\n return `\n
\n
\n \n Print bed\n
\n ${Math.round(parseFloat(states['sensor.octoprint_bed_temperature']?.state) || 0) + '\\u00B0C / target ' + Math.round(parseFloat(states['sensor.octoprint_bed_target']?.state) || 0) + '\\u00B0C'}\n
\n `;\n]]]" + }, "styles": { "card": [ { - "height": "74px", - "padding": "6px 10px" + "background": "var(--ha-card-background, var(--card-background-color))" + }, + { + "border-radius": "12px" + }, + { + "padding": "0" + }, + { + "height": "74px" + }, + { + "position": "relative" + }, + { + "box-shadow": "none" + }, + { + "border": "1px solid rgba(var(--rgb-primary-text-color), 0.08)" } ], - "name": [ - { - "font-size": "12px", - "justify-self": "start", - "opacity": "0.8" - } - ], - "icon": [ - { - "color": "#FB8C00", - "width": "26px" - } - ], - "label": [ - { - "font-size": "17px", - "font-weight": "600", - "justify-self": "start", - "color": "#FB8C00" - } - ] + "custom_fields": { + "content": [ + { + "position": "absolute" + }, + { + "inset": "0" + }, + { + "padding": "0" + } + ] + } } }, { "type": "custom:button-card", - "entity": "sensor.octoprint_print_status", - "name": "Time left", - "icon": "mdi:timer-outline", - "label": "[[[ const t = Number(states['sensor.octoprint_print_time_left'].state); return isNaN(t) ? '--' : new Date(t * 1000).toISOString().substr(11, 8); ]]]", - "color": "#43A047", + "entity": "sensor.octoprint_print_time_left", + "show_name": false, + "show_state": false, + "show_icon": false, + "tap_action": { + "action": "more-info" + }, + "custom_fields": { + "content": "[[[\n const sec = 'var(--secondary-text-color)';\n const pri = 'var(--primary-text-color)';\n const t = parseFloat(states['sensor.octoprint_print_time_left']?.state) || 0;\n const h = Math.floor(t / 3600);\n const m = Math.round((t % 3600) / 60);\n let primary = '--';\n if (t > 0) {\n primary = h > 0 ? `${h}h ${m}m` : `${m}m`;\n }\n let secondary = '';\n const et = states['sensor.octoprint_approximate_completion_time']?.state;\n if (et && !['unknown','unavailable',''].includes(et)) {\n const d = new Date(et);\n secondary = `Done: ~${d.getHours().toString().padStart(2,'0')}:${d.getMinutes().toString().padStart(2,'0')}`;\n }\n return `\n
\n
\n \n Time left\n
\n ${primary}\n ${secondary}\n
\n `;\n ]]]" + }, "styles": { "card": [ { - "height": "74px", - "padding": "6px 10px" + "background": "var(--ha-card-background, var(--card-background-color))" + }, + { + "border-radius": "12px" + }, + { + "padding": "0" + }, + { + "height": "74px" + }, + { + "position": "relative" + }, + { + "box-shadow": "none" + }, + { + "border": "1px solid rgba(var(--rgb-primary-text-color), 0.08)" } ], - "name": [ - { - "font-size": "12px", - "justify-self": "start", - "opacity": "0.8" - } - ], - "icon": [ - { - "color": "#43A047", - "width": "26px" - } - ], - "label": [ - { - "font-size": "17px", - "font-weight": "600", - "justify-self": "start", - "color": "#43A047" - } - ] + "custom_fields": { + "content": [ + { + "position": "absolute" + }, + { + "inset": "0" + }, + { + "padding": "0" + } + ] + } } }, { "type": "custom:button-card", - "entity": "sensor.octoprint_print_status", - "name": "Height", - "icon": "mdi:arrow-up-bold", - "label": "[[[ return states['sensor.octoprint_current_z'].state + ' mm'; ]]]", - "color": "#1E88E5", + "entity": "sensor.octoprint_current_z", + "show_name": false, + "show_state": false, + "show_icon": false, + "tap_action": { + "action": "more-info" + }, + "custom_fields": { + "content": "[[[\n const sec = 'var(--secondary-text-color)';\n const pri = 'var(--primary-text-color)';\n return `\n
\n
\n \n Height\n
\n ${states['sensor.octoprint_current_z']?.state + ' mm'}\n
\n `;\n]]]" + }, "styles": { "card": [ { - "height": "74px", - "padding": "6px 10px" + "background": "var(--ha-card-background, var(--card-background-color))" + }, + { + "border-radius": "12px" + }, + { + "padding": "0" + }, + { + "height": "74px" + }, + { + "position": "relative" + }, + { + "box-shadow": "none" + }, + { + "border": "1px solid rgba(var(--rgb-primary-text-color), 0.08)" } ], - "name": [ - { - "font-size": "12px", - "justify-self": "start", - "opacity": "0.8" - } - ], - "icon": [ - { - "color": "#1E88E5", - "width": "26px" - } - ], - "label": [ - { - "font-size": "17px", - "font-weight": "600", - "justify-self": "start", - "color": "#1E88E5" - } - ] + "custom_fields": { + "content": [ + { + "position": "absolute" + }, + { + "inset": "0" + }, + { + "padding": "0" + } + ] + } } } ] }, { - "type": "gauge", + "type": "custom:button-card", "entity": "sensor.octoprint_print_progress", - "unit": "%", - "min": 0, - "max": 100, - "needle": false, - "severity": { - "green": 65, - "yellow": 25, - "red": 0 + "show_name": false, + "show_state": false, + "show_icon": false, + "tap_action": { + "action": "none" + }, + "custom_fields": { + "content": "[[[\n const pct = Math.round(parseFloat(states['sensor.octoprint_print_progress']?.state) || 0);\n let file = states['sensor.octoprint_print_file']?.state || '--';\n if (['unknown','unavailable'].includes(file)) file = 'No file';\n file = file.replace(/\\.gcode$/i, '');\n return `\n
\n
\n \n Print progress\n
\n
\n ${pct}%\n ${file}\n
\n
\n
\n
\n
\n `;\n ]]]" + }, + "styles": { + "card": [ + { + "background": "var(--ha-card-background, var(--card-background-color))" + }, + { + "border-radius": "12px" + }, + { + "padding": "0" + }, + { + "height": "74px" + }, + { + "position": "relative" + }, + { + "box-shadow": "none" + }, + { + "height": "100px" + } + ], + "custom_fields": { + "content": [ + { + "position": "absolute" + }, + { + "inset": "0" + }, + { + "padding": "0" + } + ] + } } }, { - "type": "markdown", - "content": "{% set f = states('sensor.octoprint_print_file') %}\n**{{ f.replace('.gcode', '') if f not in ['unknown', 'unavailable'] else 'No file loaded' }}**\n\n{{ states('sensor.octoprint_print_status') }}{% set t = states('sensor.octoprint_approximate_completion_time') %}{% if t not in ['unknown', 'unavailable'] %} · ETA {{ (t | as_datetime | as_local).strftime('%H:%M') }}{% endif %}" - } - ] - }, - { - "type": "grid", - "cards": [ - { - "type": "heading", - "heading": "Monitor", - "heading_style": "title" - }, - { - "type": "custom:webrtc-camera", - "entity": "camera.endercamera_duckdns_org", - "mode": "mse", - "url": "octoprint", - "muted": true - }, - { - "type": "custom:mushroom-light-card", - "entity": "light.3d_printer_lights", - "name": "Printer lights", - "show_brightness_control": true, - "collapsible_controls": true + "type": "vertical-stack", + "cards": [ + { + "type": "custom:webrtc-camera", + "url": "octoprint", + "mode": "mse", + "style": "border-radius: 12px 12px 0 0; overflow: hidden;" + }, + { + "type": "custom:mushroom-light-card", + "entity": "light.3d_printer_lights", + "name": "Lamp", + "icon": "mdi:lightbulb", + "show_brightness_control": true, + "layout": "horizontal" + } + ] }, { "type": "custom:apexcharts-card", - "graph_span": "1h", - "update_interval": 15, "header": { - "title": "Temperatures (last hour)", - "show": true + "show": false }, + "graph_span": "1h", "series": [ { "entity": "sensor.octoprint_tool_0_temperature", "name": "Nozzle", - "type": "line", + "color": "#E53935", "stroke_width": 2, - "color": "#E53935" + "extend_to": "now" }, { "entity": "sensor.octoprint_bed_temperature", "name": "Bed", - "type": "line", + "color": "#FB8C00", "stroke_width": 2, - "color": "#FB8C00" + "extend_to": "now" } ], "apex_config": { "chart": { - "height": 220 + "height": 130, + "toolbar": { + "show": false + } + }, + "stroke": { + "curve": "smooth" + }, + "grid": { + "borderColor": "rgba(var(--rgb-primary-text-color), 0.05)" }, "yaxis": { "min": 0, - "max": 280 + "max": 280, + "labels": { + "style": { + "fontSize": "9px" + }, + "maxWidth": 28 + } + }, + "xaxis": { + "labels": { + "style": { + "fontSize": "9px" + } + }, + "datetimeFormatter": { + "hour": "HH:mm", + "minute": "HH:mm" + } + }, + "tooltip": { + "x": { + "format": "HH:mm" + } + }, + "legend": { + "show": true, + "fontSize": "10px", + "horizontalAlign": "left", + "offsetX": 28 } } }, { - "type": "markdown", - "content": "**Today**\n\nPrints: {{ states('sensor.octoprint_printer_prints_today') }} · Time: {{ states('sensor.octoprint_printer_print_time_today') }} h\n\nFilament: {{ (states('sensor.octoprint_filament_daily') | float(0) / 10) | round(1) }} m · Serial health: {{ (states('sensor.octoprint_serial_health_ratio') | float(0) * 100) | round(0) }}%" + "type": "custom:button-card", + "entity": "binary_sensor.octoprint_connected", + "show_name": false, + "show_icon": false, + "tap_action": { + "action": "none" + }, + "custom_fields": { + "content": "[[[\n const connected = states['binary_sensor.octoprint_connected']?.state === 'on';\n const printing = states['binary_sensor.octoprint_printing']?.state === 'on';\n const paused = states['binary_sensor.octoprint_paused']?.state === 'on';\n const health = Math.round((parseFloat(states['sensor.octoprint_serial_health_ratio']?.state) || 0) * 100);\n const prints = states['sensor.octoprint_printer_prints_today']?.state || '0';\n const ptime = states['sensor.octoprint_printer_print_time_today']?.state || '--';\n const fil = ((parseFloat(states['sensor.octoprint_filament_daily']?.state) || 0) / 10).toFixed(1);\n\n const row = (label, value, vc) => `\n
\n ${label}\n ${value}\n
`;\n return `\n
\n
\n \n Diagnostics\n
\n ${row('Connected', connected ? 'Yes' : 'No', connected ? '#4CAF50' : '#F44336')}\n ${row('Status', printing ? (paused ? 'Paused' : 'Printing') : 'Idle', printing ? '#4CAF50' : null)}\n ${row('Serial health', health + '%', health > 95 ? '#4CAF50' : health > 80 ? '#FF9800' : '#F44336')}\n ${row('Prints today', prints, null)}\n ${row('Time today', ptime + ' h', null)}\n ${row('Filament today', fil + ' m', null)}\n
\n `;\n ]]]" + }, + "styles": { + "card": [ + { + "background": "var(--ha-card-background, var(--card-background-color))" + }, + { + "border-radius": "12px" + }, + { + "padding": "0" + }, + { + "height": "74px" + }, + { + "position": "relative" + }, + { + "box-shadow": "none" + }, + { + "height": "190px" + } + ], + "custom_fields": { + "content": [ + { + "position": "absolute" + }, + { + "inset": "0" + }, + { + "padding": "0" + } + ] + } + } } ] } diff --git a/zigbee2mqtt/state.json b/zigbee2mqtt/state.json index 96260e94..60b13dc7 100644 --- a/zigbee2mqtt/state.json +++ b/zigbee2mqtt/state.json @@ -4,7 +4,7 @@ "state": "ON", "led_brightness": 100, "countdown_to_turn_off": 0, - "voltage": 122.4, + "voltage": 122, "countdown_to_turn_on": 0, "ac_frequency": 60, "power_factor": 0.14, @@ -15,21 +15,21 @@ "latest_source": "https://raw.githubusercontent.com/Koenkk/zigbee-OTA/master/images/ThirdReality/SmartPlug_Zigbee_PROD_OTA_V101_1.01.01.ota", "latest_release_notes": null }, - "power": 0.4, + "power": 0.5, "linkquality": 116, "current": 1.55, "power_on_behavior": "on" }, "0xffffb40e0607af27": { "state": "ON", - "voltage": 120.5, + "voltage": 119.8, "ac_frequency": 60, "led_brightness": 100, "countdown_to_turn_off": 0, "countdown_to_turn_on": 0, - "power": 178, - "current": 1.91, - "energy": 31.89, + "power": 229.4, + "current": 1.94, + "energy": 31.91, "power_factor": 0.98, "update": { "state": "idle", @@ -45,7 +45,7 @@ "state": "ON", "led_brightness": 100, "countdown_to_turn_off": 0, - "voltage": 121.9, + "voltage": 121.5, "countdown_to_turn_on": 0, "energy": 63.21, "power_factor": 0.3, @@ -77,10 +77,10 @@ "voltage": 120.8, "state": "ON", "ac_frequency": 60, - "energy": 127.96, - "power": 99.7, + "energy": 127.97, + "power": 97.9, "current": 0.89, - "power_factor": 0.93, + "power_factor": 0.94, "update": { "state": "idle", "installed_version": 268513381, @@ -95,13 +95,13 @@ "led_brightness": 100, "countdown_to_turn_off": 0, "countdown_to_turn_on": 0, - "voltage": 120.7, - "energy": 59.85, + "voltage": 121.1, + "energy": 59.86, "state": "ON", - "power": 48.7, - "current": 0.65, + "power": 49.3, + "current": 0.49, "ac_frequency": 60, - "power_factor": 0.8, + "power_factor": 0.73, "update": { "state": "idle", "installed_version": 268513381, @@ -114,7 +114,7 @@ }, "0xffffb40e060895b3": { "state": "ON", - "voltage": 122, + "voltage": 121.8, "ac_frequency": 60, "energy": 8.78, "current": 0.01, @@ -136,11 +136,11 @@ "0xffffb40e0608864e": { "led_brightness": 100, "countdown_to_turn_off": 0, - "voltage": 122.5, + "voltage": 122.6, "energy": 19.46, "countdown_to_turn_on": 0, "state": "ON", - "current": 0.04, + "current": 0.02, "ac_frequency": 60, "power": 0.3, "power_factor": 0.18, @@ -172,7 +172,7 @@ "0xffffb40e060893d8": { "state": "ON", "led_brightness": 100, - "voltage": 122.7, + "voltage": 122.8, "countdown_to_turn_off": 0, "countdown_to_turn_on": 0, "energy": 3.17, @@ -187,7 +187,7 @@ "latest_source": "https://raw.githubusercontent.com/Koenkk/zigbee-OTA/master/images/ThirdReality/SmartPlug_Zigbee_PROD_OTA_V101_1.01.01.ota", "latest_release_notes": null }, - "power_factor": 0.06, + "power_factor": 0.12, "power": 0.1 }, "0xa4c1380d0679ffff": { @@ -245,7 +245,7 @@ }, "0xb40e060fffe717c5": { "battery": 100, - "occupancy": false, + "occupancy": true, "tamper": false, "battery_low": false, "linkquality": 72,