adding individual lights of groups to be managed + styles modifications

This commit is contained in:
ange committed 2025-12-31 16:28:08 +01:00
1 parent bb6d136c70
commit 0660ca55ee
9 files changed
+1209 -458

No files matched your search

@@ -604,9 +604,10 @@ function r5(r6) {
// src/styles.ts
var mainStyles = i`
:host {
--lpm-temp-warm-color: #ff9800;
--lpm-temp-neutral-color: #9e9e9e;
--lpm-temp-warm-color: #ffe600ff;
--lpm-temp-neutral-color: #ffffff;
--lpm-temp-cold-color: #2196f3;
--lpm-temp-inactive-color: rgba(255, 255, 255, 0.5);
--lpm-button-radius: 8px;
--lpm-preset-radius: 12px;
--lpm-spacing: 8px;
@@ -735,46 +736,49 @@ var mainStyles = i`
.temp-button {
flex: 1;
padding: 12px var(--lpm-spacing);
padding: 10px var(--lpm-spacing);
border: none;
border-radius: var(--lpm-button-radius);
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
justify-content: center;
gap: 6px;
background: var(--primary-background-color);
color: var(--primary-text-color);
color: var(--lpm-temp-inactive-color);
transition: all var(--lpm-transition);
font-family: inherit;
font-size: 12px;
font-size: 13px;
font-weight: 500;
}
.temp-button:hover {
.temp-button:hover:not(:disabled) {
background: var(--secondary-background-color);
}
.temp-button:active {
transform: scale(0.95);
.temp-button:active:not(:disabled) {
transform: scale(0.97);
}
.temp-button:disabled {
opacity: 0.5;
opacity: 0.4;
cursor: not-allowed;
}
.temp-button.warm {
border-bottom: 3px solid var(--lpm-temp-warm-color);
.temp-button.active.warm {
color: var(--lpm-temp-warm-color);
}
.temp-button.neutral {
border-bottom: 3px solid var(--lpm-temp-neutral-color);
.temp-button.active.neutral {
color: var(--lpm-temp-neutral-color);
}
.temp-button.cold {
border-bottom: 3px solid var(--lpm-temp-cold-color);
.temp-button.active.cold {
color: var(--lpm-temp-cold-color);
}
.temp-button ha-icon {
--mdc-icon-size: 24px;
--mdc-icon-size: 20px;
}
/* Lights Panel */
@@ -901,45 +905,47 @@ var mainStyles = i`
/* Mini Temperature Buttons for individual lights */
.light-temp-buttons {
display: flex;
gap: 4px;
gap: 2px;
}
.light-temp-button {
width: 28px;
height: 28px;
border-radius: 4px;
border-radius: 6px;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
background: var(--primary-background-color);
color: var(--primary-text-color);
color: var(--lpm-temp-inactive-color);
transition: all var(--lpm-transition);
padding: 0;
}
.light-temp-button:hover {
.light-temp-button:hover:not(:disabled) {
background: var(--secondary-background-color);
}
.light-temp-button:active {
.light-temp-button:active:not(:disabled) {
transform: scale(0.95);
}
.light-temp-button:disabled {
opacity: 0.5;
opacity: 0.4;
cursor: not-allowed;
}
.light-temp-button.warm {
border-bottom: 2px solid var(--lpm-temp-warm-color);
.light-temp-button.active.warm {
color: var(--lpm-temp-warm-color);
}
.light-temp-button.neutral {
border-bottom: 2px solid var(--lpm-temp-neutral-color);
.light-temp-button.active.neutral {
color: var(--lpm-temp-neutral-color);
}
.light-temp-button.cold {
border-bottom: 2px solid var(--lpm-temp-cold-color);
.light-temp-button.active.cold {
color: var(--lpm-temp-cold-color);
}
.light-temp-button ha-icon {
@@ -1078,6 +1084,7 @@ var mainStyles = i`
.popup-button:hover {
opacity: 0.9;
}
.popup-button:active {
transform: scale(0.95);
}
@@ -1090,6 +1097,12 @@ var DEFAULT_TEMPERATURES = {
cold: 200
};
var DEFAULT_PRESETS = 4;
function normalizeLightConfig(light) {
if (typeof light === "string") {
return { entity: light };
}
return { entity: light.entity, name: light.name };
}
function validateConfig(config) {
if (!config.group) {
throw new Error('Config error: "group" is required');
@@ -1097,11 +1110,16 @@ function validateConfig(config) {
if (!config.group.startsWith("light.")) {
throw new Error(`Config error: "${config.group}" is not a light.* entity`);
}
const lights = [];
if (config.lights) {
for (const light of config.lights) {
if (!light.startsWith("light.")) {
throw new Error(`Config error: "${light}" is not a light.* entity`);
const normalized = normalizeLightConfig(light);
if (!normalized.entity.startsWith("light.")) {
throw new Error(
`Config error: "${normalized.entity}" is not a light.* entity`
);
}
lights.push(normalized);
}
}
if (config.presets !== void 0 && (config.presets < 1 || config.presets > 4)) {
@@ -1110,7 +1128,7 @@ function validateConfig(config) {
return {
group: config.group,
title: config.title,
lights: config.lights || [],
lights,
temperatures: {
warm: config.temperatures?.warm || DEFAULT_TEMPERATURES.warm,
neutral: config.temperatures?.neutral || DEFAULT_TEMPERATURES.neutral,
@@ -1125,7 +1143,10 @@ var getBrightnessPercent = (entity) => {
const brightness = entity?.attributes.brightness;
return brightness ? Math.round(brightness / 255 * 100) : 0;
};
var getEntityName = (entity) => entity?.attributes.friendly_name || entity?.entity_id || "Unknown";
var getEntityName = (entity, customName) => {
if (customName) return customName;
return entity?.attributes.friendly_name || entity?.entity_id || "Unknown";
};
var supportsColorTemp = (entity) => {
const modes = entity?.attributes.supported_color_modes || [];
return modes.includes("color_temp");
@@ -1135,9 +1156,19 @@ function getLightsFromGroup(groupEntity, configLights) {
return configLights;
}
if (groupEntity?.attributes.entity_id) {
return groupEntity.attributes.entity_id;
return groupEntity.attributes.entity_id.map((entity) => ({ entity }));
}
return groupEntity ? [groupEntity.entity_id] : [];
return groupEntity ? [{ entity: groupEntity.entity_id }] : [];
}
function getCurrentTempZone(entity, temperatures) {
if (!entity || entity.state !== "on") return null;
const colorTemp = entity.attributes.color_temp;
if (colorTemp === void 0) return null;
const warmNeutralMid = (temperatures.warm + temperatures.neutral) / 2;
const neutralColdMid = (temperatures.neutral + temperatures.cold) / 2;
if (colorTemp >= warmNeutralMid) return "warm";
if (colorTemp <= neutralColdMid) return "cold";
return "neutral";
}
// src/locales/en.json
@@ -1225,7 +1256,7 @@ function getTranslations(locale) {
}
// src/editor.ts
var SCHEMA = [
var MAIN_SCHEMA = [
{
name: "group",
required: true,
@@ -1241,15 +1272,6 @@ var SCHEMA = [
text: {}
}
},
{
name: "lights",
selector: {
entity: {
domain: "light",
multiple: true
}
}
},
{
name: "presets",
selector: {
@@ -1268,7 +1290,6 @@ var LightPresetManagerEditor = class extends i4 {
const labels = {
group: "Group (required)",
title: "Title",
lights: "Individual Lights",
presets: "Number of Presets (1-4)"
};
return labels[schema.name] || schema.name;
@@ -1277,19 +1298,78 @@ var LightPresetManagerEditor = class extends i4 {
setConfig(config) {
this._config = config;
}
_valueChanged(ev) {
const config = ev.detail.value;
if (this._config?.temperatures) {
config.temperatures = this._config.temperatures;
}
_dispatchConfig(newConfig) {
const event = new CustomEvent("config-changed", {
detail: { config },
detail: { config: newConfig },
bubbles: true,
composed: true
});
this.dispatchEvent(event);
this._config = config;
this._config = newConfig;
}
_mainValueChanged(ev) {
if (!this._config) return;
const newConfig = {
...this._config,
...ev.detail.value
};
this._dispatchConfig(newConfig);
}
// ---------------------------------------------------------------------------
// Lights management
// ---------------------------------------------------------------------------
_normalizeLight(light) {
if (typeof light === "string") {
return { entity: light };
}
return light;
}
_getLights() {
if (!this._config?.lights) return [];
return this._config.lights.map(this._normalizeLight);
}
_lightEntityChanged(index, ev) {
if (!this._config) return;
const value = ev.detail.value;
const lights = this._getLights();
if (value) {
lights[index] = { ...lights[index], entity: value };
}
this._dispatchConfig({ ...this._config, lights });
}
_lightNameChanged(index, ev) {
if (!this._config) return;
const target = ev.target;
const value = target.value || void 0;
const lights = this._getLights();
if (value) {
lights[index] = { ...lights[index], name: value };
} else {
delete lights[index].name;
}
this._dispatchConfig({ ...this._config, lights });
}
_addLight() {
if (!this._config) return;
const lights = this._getLights();
lights.push({ entity: "" });
this._dispatchConfig({ ...this._config, lights });
}
_removeLight(index) {
if (!this._config) return;
const lights = this._getLights();
lights.splice(index, 1);
const newConfig = { ...this._config };
if (lights.length > 0) {
newConfig.lights = lights;
} else {
delete newConfig.lights;
}
this._dispatchConfig(newConfig);
}
// ---------------------------------------------------------------------------
// Temperatures
// ---------------------------------------------------------------------------
_tempChanged(tempKey, ev) {
if (!this._config) return;
const target = ev.target;
@@ -1306,30 +1386,77 @@ var LightPresetManagerEditor = class extends i4 {
} else {
delete newConfig.temperatures;
}
const event = new CustomEvent("config-changed", {
detail: { config: newConfig },
bubbles: true,
composed: true
});
this.dispatchEvent(event);
this._config = newConfig;
this._dispatchConfig(newConfig);
}
// ---------------------------------------------------------------------------
// Render
// ---------------------------------------------------------------------------
render() {
if (!this.hass || !this._config) {
return b2``;
}
const lights = this._getLights();
const entitySelector = { entity: { domain: "light" } };
return b2`
<div class="form">
<!-- Main config -->
<ha-form
.hass=${this.hass}
.data=${this._config}
.schema=${SCHEMA}
.schema=${MAIN_SCHEMA}
.computeLabel=${this._computeLabel}
@value-changed=${this._valueChanged}
@value-changed=${this._mainValueChanged}
></ha-form>
<div class="temps-section">
<div class="temps-title">Color Temperatures (mireds)</div>
<!-- Individual Lights -->
<div class="section">
<div class="section-title">Individual Lights</div>
<div class="lights-list">
${lights.map(
(light, index) => b2`
<div class="light-item">
<div class="light-item-fields">
<div class="light-item-row">
<label>Entity</label>
<ha-selector-entity
.hass=${this.hass}
.selector=${entitySelector}
.value=${light.entity}
.required=${true}
@value-changed=${(ev) => this._lightEntityChanged(index, ev)}
></ha-selector-entity>
</div>
<div class="light-item-row">
<label>Name</label>
<input
type="text"
.value=${light.name || ""}
@input=${(ev) => this._lightNameChanged(index, ev)}
placeholder="Custom display name"
/>
</div>
</div>
<ha-icon
class="remove-btn"
icon="mdi:close"
@click=${() => this._removeLight(index)}
></ha-icon>
</div>
`
)}
<div class="add-btn" @click=${this._addLight}>
<ha-icon icon="mdi:plus"></ha-icon>
Add light
</div>
</div>
<span class="helper"
>Optional: individual lights for preset control</span
>
</div>
<!-- Temperatures -->
<div class="section">
<div class="section-title">Color Temperatures (mireds)</div>
<div class="temps-row">
<div class="temp-input">
<label>Warm</label>
@@ -1371,19 +1498,98 @@ LightPresetManagerEditor.styles = i`
gap: 16px;
}
.temps-section {
.section {
border: 1px solid var(--divider-color);
border-radius: 8px;
padding: 16px;
}
.temps-title {
.section-title {
font-weight: 500;
font-size: 14px;
color: var(--primary-text-color);
margin-bottom: 12px;
}
.lights-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.light-item {
display: flex;
gap: 8px;
align-items: flex-start;
padding: 8px;
background: var(--secondary-background-color);
border-radius: 8px;
}
.light-item-fields {
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
}
.light-item-row {
display: flex;
gap: 8px;
align-items: center;
}
.light-item-row ha-selector-entity {
flex: 1;
}
.light-item-row input {
flex: 1;
padding: 8px 12px;
border: 1px solid var(--divider-color);
border-radius: 4px;
font-size: 14px;
background: var(--primary-background-color);
color: var(--primary-text-color);
font-family: inherit;
}
.light-item-row input:focus {
outline: none;
border-color: var(--primary-color);
}
.light-item-row label {
font-size: 12px;
color: var(--secondary-text-color);
min-width: 50px;
}
.remove-btn {
color: var(--error-color);
cursor: pointer;
padding: 8px;
margin-top: 4px;
}
.remove-btn:hover {
opacity: 0.8;
}
.add-btn {
color: var(--primary-color);
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
font-size: 14px;
padding: 8px 0;
}
.add-btn:hover {
opacity: 0.8;
}
.temps-row {
display: flex;
gap: 8px;
@@ -1417,6 +1623,12 @@ LightPresetManagerEditor.styles = i`
outline: none;
border-color: var(--primary-color);
}
.helper {
font-size: 12px;
color: var(--secondary-text-color);
margin-top: 4px;
}
`;
__decorateClass([
n4({ attribute: false })
@@ -1428,7 +1640,7 @@ LightPresetManagerEditor = __decorateClass([
t3("light-preset-manager-editor")
], LightPresetManagerEditor);
console.log(
"%c LIGHT-PRESET-MANAGER-EDITOR %c v0.4.2 ",
"%c LIGHT-PRESET-MANAGER-EDITOR %c v0.5.0 ",
"background: #9b59b6; color: white; font-weight: bold; border-radius: 4px 0 0 4px;",
"background: #2ecc71; color: white; border-radius: 0 4px 4px 0;"
);
@@ -1474,10 +1686,13 @@ var LightPresetManager = class extends i4 {
get _supportsColorTemp() {
return supportsColorTemp(this._group);
}
get _currentTempZone() {
if (!this._config) return null;
return getCurrentTempZone(this._group, this._config.temperatures);
}
get _lights() {
if (!this.hass || !this._config) return [];
const lightIds = getLightsFromGroup(this._group, this._config.lights);
return lightIds.map((id) => this.hass.states[id]).filter((e5) => e5 !== void 0);
return getLightsFromGroup(this._group, this._config.lights);
}
// ---------------------------------------------------------------------------
// Actions - Global
@@ -1537,11 +1752,9 @@ var LightPresetManager = class extends i4 {
// ---------------------------------------------------------------------------
render() {
if (!this.hass || !this._config || !this._t) {
return b2`<ha-card
><div class="card-content">
${this._t?.card.loading || "Loading..."}
</div></ha-card
>`;
return b2`<ha-card>
<div class="card-content">${this._t?.card.loading || "Loading..."}</div>
</ha-card>`;
}
return b2`
<ha-card .header=${this._config.title || ""}>
@@ -1585,12 +1798,13 @@ var LightPresetManager = class extends i4 {
}
_renderGlobalTemperature() {
const isOn = this._isOn;
const currentZone = this._currentTempZone;
const t4 = this._t;
return b2`
<div class="temp-section">
<div class="temp-buttons">
<button
class="temp-button warm"
class="temp-button warm ${currentZone === "warm" ? "active" : ""}"
@click=${() => this._setTemperature("warm")}
?disabled=${!isOn}
>
@@ -1598,7 +1812,7 @@ var LightPresetManager = class extends i4 {
${t4.temperature.warm}
</button>
<button
class="temp-button neutral"
class="temp-button neutral ${currentZone === "neutral" ? "active" : ""}"
@click=${() => this._setTemperature("neutral")}
?disabled=${!isOn}
>
@@ -1606,7 +1820,7 @@ var LightPresetManager = class extends i4 {
${t4.temperature.neutral}
</button>
<button
class="temp-button cold"
class="temp-button cold ${currentZone === "cold" ? "active" : ""}"
@click=${() => this._setTemperature("cold")}
?disabled=${!isOn}
>
@@ -1626,22 +1840,26 @@ var LightPresetManager = class extends i4 {
>
</div>
<div class="lights-list">
${this._lights.map((entity) => this._renderLightRow(entity))}
${this._lights.map(
(lightConfig) => this._renderLightRow(lightConfig)
)}
</div>
</div>
`;
}
_renderLightRow(entity) {
_renderLightRow(lightConfig) {
const entity = this.hass?.states[lightConfig.entity];
const isOn = isEntityOn(entity);
const available = isEntityAvailable(entity);
const brightness = getBrightnessPercent(entity);
const name = getEntityName(entity);
const name = getEntityName(entity, lightConfig.name);
const hasColorTemp = supportsColorTemp(entity);
const currentZone = this._config ? getCurrentTempZone(entity, this._config.temperatures) : null;
return b2`
<div class="light-row">
<button
class="light-toggle ${isOn ? "on" : ""}"
@click=${() => this._toggleLight(entity.entity_id)}
@click=${() => this._toggleLight(lightConfig.entity)}
?disabled=${!available}
>
<ha-icon icon="mdi:lightbulb${isOn ? "" : "-outline"}"></ha-icon>
@@ -1658,31 +1876,31 @@ var LightPresetManager = class extends i4 {
min="1"
max="100"
.value=${String(isOn ? brightness : 0)}
@change=${(e5) => this._setLightBrightness(entity.entity_id, e5)}
@change=${(e5) => this._setLightBrightness(lightConfig.entity, e5)}
?disabled=${!isOn || !available}
/>
${hasColorTemp ? b2`
<div class="light-temp-buttons">
<button
class="light-temp-button warm"
@click=${() => this._setLightTemperature(entity.entity_id, "warm")}
class="light-temp-button warm ${currentZone === "warm" ? "active" : ""}"
@click=${() => this._setLightTemperature(lightConfig.entity, "warm")}
?disabled=${!isOn || !available}
title="${this._t.temperature.warm}"
>
<ha-icon icon="mdi:weather-sunny"></ha-icon>
</button>
<button
class="light-temp-button neutral"
@click=${() => this._setLightTemperature(entity.entity_id, "neutral")}
class="light-temp-button neutral ${currentZone === "neutral" ? "active" : ""}"
@click=${() => this._setLightTemperature(lightConfig.entity, "neutral")}
?disabled=${!isOn || !available}
title="${this._t.temperature.neutral}"
>
<ha-icon icon="mdi:circle-half-full"></ha-icon>
</button>
<button
class="light-temp-button cold"
@click=${() => this._setLightTemperature(entity.entity_id, "cold")}
class="light-temp-button cold ${currentZone === "cold" ? "active" : ""}"
@click=${() => this._setLightTemperature(lightConfig.entity, "cold")}
?disabled=${!isOn || !available}
title="${this._t.temperature.cold}"
>
@@ -1712,9 +1930,15 @@ LightPresetManager = __decorateClass([
t3("light-preset-manager")
], LightPresetManager);
window.customCards = window.customCards || [];
window.cu;
window.customCards.push({
type: "light-preset-manager",
name: "Light Preset Manager",
description: "Light control panel with saveable presets",
preview: true,
documentationURL: "https://github.com/your-repo/light-preset-manager"
});
console.log(
"%c LIGHT-PRESET-MANAGER %c v0.4.1 ",
"%c LIGHT-PRESET-MANAGER %c v0.5.3 ",
"background: #3498db; color: white; font-weight: bold; border-radius: 4px 0 0 4px;",
"background: #2ecc71; color: white; border-radius: 0 4px 4px 0;"
);
+236 -40
View File
@@ -1,9 +1,13 @@
import { LitElement, html, css } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import type { HomeAssistant, LightPresetManagerConfig } from "./types";
import type {
HomeAssistant,
LightPresetManagerConfig,
LightConfig,
} from "./types";
const SCHEMA = [
const MAIN_SCHEMA = [
{
name: "group",
required: true,
@@ -19,15 +23,6 @@ const SCHEMA = [
text: {},
},
},
{
name: "lights",
selector: {
entity: {
domain: "light",
multiple: true,
},
},
},
{
name: "presets",
selector: {
@@ -52,19 +47,98 @@ export class LightPresetManagerEditor extends LitElement {
gap: 16px;
}
.temps-section {
.section {
border: 1px solid var(--divider-color);
border-radius: 8px;
padding: 16px;
}
.temps-title {
.section-title {
font-weight: 500;
font-size: 14px;
color: var(--primary-text-color);
margin-bottom: 12px;
}
.lights-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.light-item {
display: flex;
gap: 8px;
align-items: flex-start;
padding: 8px;
background: var(--secondary-background-color);
border-radius: 8px;
}
.light-item-fields {
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
}
.light-item-row {
display: flex;
gap: 8px;
align-items: center;
}
.light-item-row ha-selector-entity {
flex: 1;
}
.light-item-row input {
flex: 1;
padding: 8px 12px;
border: 1px solid var(--divider-color);
border-radius: 4px;
font-size: 14px;
background: var(--primary-background-color);
color: var(--primary-text-color);
font-family: inherit;
}
.light-item-row input:focus {
outline: none;
border-color: var(--primary-color);
}
.light-item-row label {
font-size: 12px;
color: var(--secondary-text-color);
min-width: 50px;
}
.remove-btn {
color: var(--error-color);
cursor: pointer;
padding: 8px;
margin-top: 4px;
}
.remove-btn:hover {
opacity: 0.8;
}
.add-btn {
color: var(--primary-color);
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
font-size: 14px;
padding: 8px 0;
}
.add-btn:hover {
opacity: 0.8;
}
.temps-row {
display: flex;
gap: 8px;
@@ -98,30 +172,105 @@ export class LightPresetManagerEditor extends LitElement {
outline: none;
border-color: var(--primary-color);
}
.helper {
font-size: 12px;
color: var(--secondary-text-color);
margin-top: 4px;
}
`;
setConfig(config: LightPresetManagerConfig): void {
this._config = config;
}
private _valueChanged(ev: CustomEvent): void {
const config = ev.detail.value as LightPresetManagerConfig;
// Keep temperatures from current config (ha-form doesn't handle them)
if (this._config?.temperatures) {
config.temperatures = this._config.temperatures;
}
private _dispatchConfig(newConfig: LightPresetManagerConfig): void {
const event = new CustomEvent("config-changed", {
detail: { config },
detail: { config: newConfig },
bubbles: true,
composed: true,
});
this.dispatchEvent(event);
this._config = config;
this._config = newConfig;
}
private _mainValueChanged(ev: CustomEvent): void {
if (!this._config) return;
const newConfig = {
...this._config,
...ev.detail.value,
};
this._dispatchConfig(newConfig);
}
// ---------------------------------------------------------------------------
// Lights management
// ---------------------------------------------------------------------------
private _normalizeLight(light: string | LightConfig): LightConfig {
if (typeof light === "string") {
return { entity: light };
}
return light;
}
private _getLights(): LightConfig[] {
if (!this._config?.lights) return [];
return this._config.lights.map(this._normalizeLight);
}
private _lightEntityChanged(index: number, ev: CustomEvent): void {
if (!this._config) return;
const value = ev.detail.value;
const lights = this._getLights();
if (value) {
lights[index] = { ...lights[index], entity: value };
}
this._dispatchConfig({ ...this._config, lights });
}
private _lightNameChanged(index: number, ev: Event): void {
if (!this._config) return;
const target = ev.target as HTMLInputElement;
const value = target.value || undefined;
const lights = this._getLights();
if (value) {
lights[index] = { ...lights[index], name: value };
} else {
delete lights[index].name;
}
this._dispatchConfig({ ...this._config, lights });
}
private _addLight(): void {
if (!this._config) return;
const lights = this._getLights();
lights.push({ entity: "" });
this._dispatchConfig({ ...this._config, lights });
}
private _removeLight(index: number): void {
if (!this._config) return;
const lights = this._getLights();
lights.splice(index, 1);
const newConfig = { ...this._config };
if (lights.length > 0) {
newConfig.lights = lights;
} else {
delete newConfig.lights;
}
this._dispatchConfig(newConfig);
}
// ---------------------------------------------------------------------------
// Temperatures
// ---------------------------------------------------------------------------
private _tempChanged(tempKey: "warm" | "neutral" | "cold", ev: Event): void {
if (!this._config) return;
const target = ev.target as HTMLInputElement;
@@ -141,34 +290,83 @@ export class LightPresetManagerEditor extends LitElement {
} else {
delete newConfig.temperatures;
}
const event = new CustomEvent("config-changed", {
detail: { config: newConfig },
bubbles: true,
composed: true,
});
this.dispatchEvent(event);
this._config = newConfig;
this._dispatchConfig(newConfig);
}
// ---------------------------------------------------------------------------
// Render
// ---------------------------------------------------------------------------
protected render() {
if (!this.hass || !this._config) {
return html``;
}
const lights = this._getLights();
const entitySelector = { entity: { domain: "light" } };
return html`
<div class="form">
<!-- Main config -->
<ha-form
.hass=${this.hass}
.data=${this._config}
.schema=${SCHEMA}
.schema=${MAIN_SCHEMA}
.computeLabel=${this._computeLabel}
@value-changed=${this._valueChanged}
@value-changed=${this._mainValueChanged}
></ha-form>
<div class="temps-section">
<div class="temps-title">Color Temperatures (mireds)</div>
<!-- Individual Lights -->
<div class="section">
<div class="section-title">Individual Lights</div>
<div class="lights-list">
${lights.map(
(light, index) => html`
<div class="light-item">
<div class="light-item-fields">
<div class="light-item-row">
<label>Entity</label>
<ha-selector-entity
.hass=${this.hass}
.selector=${entitySelector}
.value=${light.entity}
.required=${true}
@value-changed=${(ev: CustomEvent) =>
this._lightEntityChanged(index, ev)}
></ha-selector-entity>
</div>
<div class="light-item-row">
<label>Name</label>
<input
type="text"
.value=${light.name || ""}
@input=${(ev: Event) =>
this._lightNameChanged(index, ev)}
placeholder="Custom display name"
/>
</div>
</div>
<ha-icon
class="remove-btn"
icon="mdi:close"
@click=${() => this._removeLight(index)}
></ha-icon>
</div>
`
)}
<div class="add-btn" @click=${this._addLight}>
<ha-icon icon="mdi:plus"></ha-icon>
Add light
</div>
</div>
<span class="helper"
>Optional: individual lights for preset control</span
>
</div>
<!-- Temperatures -->
<div class="section">
<div class="section-title">Color Temperatures (mireds)</div>
<div class="temps-row">
<div class="temp-input">
<label>Warm</label>
@@ -207,7 +405,6 @@ export class LightPresetManagerEditor extends LitElement {
const labels: Record<string, string> = {
group: "Group (required)",
title: "Title",
lights: "Individual Lights",
presets: "Number of Presets (1-4)",
};
return labels[schema.name] || schema.name;
@@ -215,8 +412,7 @@ export class LightPresetManagerEditor extends LitElement {
}
console.log(
"%c LIGHT-PRESET-MANAGER-EDITOR %c v0.4.2 ",
"%c LIGHT-PRESET-MANAGER-EDITOR %c v0.5.0 ",
"background: #9b59b6; color: white; font-weight: bold; border-radius: 4px 0 0 4px;",
"background: #2ecc71; color: white; border-radius: 0 4px 4px 0;"
);
+49 -28
View File
@@ -6,6 +6,7 @@ import type {
HassEntity,
LightPresetManagerConfig,
LightPresetManagerConfigInternal,
LightConfigInternal,
TemperatureType,
} from "./types";
import type { Translations } from "./locales";
@@ -18,6 +19,7 @@ import {
isEntityAvailable,
getLightsFromGroup,
supportsColorTemp,
getCurrentTempZone,
} from "./utils";
import { detectLocale, getTranslations } from "./locales";
@@ -82,14 +84,14 @@ export class LightPresetManager extends LitElement {
return supportsColorTemp(this._group);
}
private get _lights(): HassEntity[] {
private get _currentTempZone(): TemperatureType | null {
if (!this._config) return null;
return getCurrentTempZone(this._group, this._config.temperatures);
}
private get _lights(): LightConfigInternal[] {
if (!this.hass || !this._config) return [];
const lightIds = getLightsFromGroup(this._group, this._config.lights);
return lightIds
.map((id) => this.hass!.states[id])
.filter((e): e is HassEntity => e !== undefined);
return getLightsFromGroup(this._group, this._config.lights);
}
// ---------------------------------------------------------------------------
@@ -159,11 +161,9 @@ export class LightPresetManager extends LitElement {
render() {
if (!this.hass || !this._config || !this._t) {
return html`<ha-card
><div class="card-content">
${this._t?.card.loading || "Loading..."}
</div></ha-card
>`;
return html`<ha-card>
<div class="card-content">${this._t?.card.loading || "Loading..."}</div>
</ha-card>`;
}
return html`
@@ -211,13 +211,14 @@ export class LightPresetManager extends LitElement {
private _renderGlobalTemperature() {
const isOn = this._isOn;
const currentZone = this._currentTempZone;
const t = this._t!;
return html`
<div class="temp-section">
<div class="temp-buttons">
<button
class="temp-button warm"
class="temp-button warm ${currentZone === "warm" ? "active" : ""}"
@click=${() => this._setTemperature("warm")}
?disabled=${!isOn}
>
@@ -225,7 +226,9 @@ export class LightPresetManager extends LitElement {
${t.temperature.warm}
</button>
<button
class="temp-button neutral"
class="temp-button neutral ${currentZone === "neutral"
? "active"
: ""}"
@click=${() => this._setTemperature("neutral")}
?disabled=${!isOn}
>
@@ -233,7 +236,7 @@ export class LightPresetManager extends LitElement {
${t.temperature.neutral}
</button>
<button
class="temp-button cold"
class="temp-button cold ${currentZone === "cold" ? "active" : ""}"
@click=${() => this._setTemperature("cold")}
?disabled=${!isOn}
>
@@ -254,24 +257,30 @@ export class LightPresetManager extends LitElement {
>
</div>
<div class="lights-list">
${this._lights.map((entity) => this._renderLightRow(entity))}
${this._lights.map((lightConfig) =>
this._renderLightRow(lightConfig)
)}
</div>
</div>
`;
}
private _renderLightRow(entity: HassEntity) {
private _renderLightRow(lightConfig: LightConfigInternal) {
const entity = this.hass?.states[lightConfig.entity];
const isOn = isEntityOn(entity);
const available = isEntityAvailable(entity);
const brightness = getBrightnessPercent(entity);
const name = getEntityName(entity);
const name = getEntityName(entity, lightConfig.name);
const hasColorTemp = supportsColorTemp(entity);
const currentZone = this._config
? getCurrentTempZone(entity, this._config.temperatures)
: null;
return html`
<div class="light-row">
<button
class="light-toggle ${isOn ? "on" : ""}"
@click=${() => this._toggleLight(entity.entity_id)}
@click=${() => this._toggleLight(lightConfig.entity)}
?disabled=${!available}
>
<ha-icon icon="mdi:lightbulb${isOn ? "" : "-outline"}"></ha-icon>
@@ -289,7 +298,7 @@ export class LightPresetManager extends LitElement {
max="100"
.value=${String(isOn ? brightness : 0)}
@change=${(e: Event) =>
this._setLightBrightness(entity.entity_id, e)}
this._setLightBrightness(lightConfig.entity, e)}
?disabled=${!isOn || !available}
/>
@@ -297,27 +306,33 @@ export class LightPresetManager extends LitElement {
? html`
<div class="light-temp-buttons">
<button
class="light-temp-button warm"
class="light-temp-button warm ${currentZone === "warm"
? "active"
: ""}"
@click=${() =>
this._setLightTemperature(entity.entity_id, "warm")}
this._setLightTemperature(lightConfig.entity, "warm")}
?disabled=${!isOn || !available}
title="${this._t!.temperature.warm}"
>
<ha-icon icon="mdi:weather-sunny"></ha-icon>
</button>
<button
class="light-temp-button neutral"
class="light-temp-button neutral ${currentZone === "neutral"
? "active"
: ""}"
@click=${() =>
this._setLightTemperature(entity.entity_id, "neutral")}
this._setLightTemperature(lightConfig.entity, "neutral")}
?disabled=${!isOn || !available}
title="${this._t!.temperature.neutral}"
>
<ha-icon icon="mdi:circle-half-full"></ha-icon>
</button>
<button
class="light-temp-button cold"
class="light-temp-button cold ${currentZone === "cold"
? "active"
: ""}"
@click=${() =>
this._setLightTemperature(entity.entity_id, "cold")}
this._setLightTemperature(lightConfig.entity, "cold")}
?disabled=${!isOn || !available}
title="${this._t!.temperature.cold}"
>
@@ -338,10 +353,16 @@ export class LightPresetManager extends LitElement {
// Registration
(window as any).customCards = (window as any).customCards || [];
(window as any).cu;
(window as any).customCards.push({
type: "light-preset-manager",
name: "Light Preset Manager",
description: "Light control panel with saveable presets",
preview: true,
documentationURL: "https://github.com/your-repo/light-preset-manager",
});
console.log(
"%c LIGHT-PRESET-MANAGER %c v0.4.1 ",
"%c LIGHT-PRESET-MANAGER %c v0.5.3 ",
"background: #3498db; color: white; font-weight: bold; border-radius: 4px 0 0 4px;",
"background: #2ecc71; color: white; border-radius: 0 4px 4px 0;"
);
+37 -30
View File
@@ -2,9 +2,10 @@ import { css } from "lit";
export const mainStyles = css`
:host {
--lpm-temp-warm-color: #ff9800;
--lpm-temp-neutral-color: #9e9e9e;
--lpm-temp-warm-color: #ffae00ff;
--lpm-temp-neutral-color: #ffffff;
--lpm-temp-cold-color: #2196f3;
--lpm-temp-inactive-color: rgba(255, 255, 255, 0.5);
--lpm-button-radius: 8px;
--lpm-preset-radius: 12px;
--lpm-spacing: 8px;
@@ -133,46 +134,49 @@ export const mainStyles = css`
.temp-button {
flex: 1;
padding: 12px var(--lpm-spacing);
padding: 10px var(--lpm-spacing);
border: none;
border-radius: var(--lpm-button-radius);
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
justify-content: center;
gap: 6px;
background: var(--primary-background-color);
color: var(--primary-text-color);
color: var(--lpm-temp-inactive-color);
transition: all var(--lpm-transition);
font-family: inherit;
font-size: 12px;
font-size: 13px;
font-weight: 500;
}
.temp-button:hover {
.temp-button:hover:not(:disabled) {
background: var(--secondary-background-color);
}
.temp-button:active {
transform: scale(0.95);
.temp-button:active:not(:disabled) {
transform: scale(0.97);
}
.temp-button:disabled {
opacity: 0.5;
opacity: 0.4;
cursor: not-allowed;
}
.temp-button.warm {
border-bottom: 3px solid var(--lpm-temp-warm-color);
.temp-button.active.warm {
color: var(--lpm-temp-warm-color);
}
.temp-button.neutral {
border-bottom: 3px solid var(--lpm-temp-neutral-color);
.temp-button.active.neutral {
color: var(--lpm-temp-neutral-color);
}
.temp-button.cold {
border-bottom: 3px solid var(--lpm-temp-cold-color);
.temp-button.active.cold {
color: var(--lpm-temp-cold-color);
}
.temp-button ha-icon {
--mdc-icon-size: 24px;
--mdc-icon-size: 20px;
}
/* Lights Panel */
@@ -299,45 +303,47 @@ export const mainStyles = css`
/* Mini Temperature Buttons for individual lights */
.light-temp-buttons {
display: flex;
gap: 4px;
gap: 2px;
}
.light-temp-button {
width: 28px;
height: 28px;
border-radius: 4px;
border-radius: 6px;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
background: var(--primary-background-color);
color: var(--primary-text-color);
color: var(--lpm-temp-inactive-color);
transition: all var(--lpm-transition);
padding: 0;
}
.light-temp-button:hover {
.light-temp-button:hover:not(:disabled) {
background: var(--secondary-background-color);
}
.light-temp-button:active {
.light-temp-button:active:not(:disabled) {
transform: scale(0.95);
}
.light-temp-button:disabled {
opacity: 0.5;
opacity: 0.4;
cursor: not-allowed;
}
.light-temp-button.warm {
border-bottom: 2px solid var(--lpm-temp-warm-color);
.light-temp-button.active.warm {
color: var(--lpm-temp-warm-color);
}
.light-temp-button.neutral {
border-bottom: 2px solid var(--lpm-temp-neutral-color);
.light-temp-button.active.neutral {
color: var(--lpm-temp-neutral-color);
}
.light-temp-button.cold {
border-bottom: 2px solid var(--lpm-temp-cold-color);
.light-temp-button.active.cold {
color: var(--lpm-temp-cold-color);
}
.light-temp-button ha-icon {
@@ -476,6 +482,7 @@ export const mainStyles = css`
.popup-button:hover {
opacity: 0.9;
}
.popup-button:active {
transform: scale(0.95);
}
+13 -3
View File
@@ -8,6 +8,11 @@ export interface TemperaturesConfig {
cold: number;
}
export interface LightConfig {
entity: string;
name?: string;
}
export interface LightPresetManagerConfig {
// Required: main group or light for global control
group: string;
@@ -15,8 +20,8 @@ export interface LightPresetManagerConfig {
// Optional: card header title
title?: string;
// Optional: individual lights for presets
lights?: string[];
// Optional: individual lights for presets (string or object with name)
lights?: (string | LightConfig)[];
// Optional: color temperatures in mireds
temperatures?: Partial<TemperaturesConfig>;
@@ -25,10 +30,15 @@ export interface LightPresetManagerConfig {
presets?: number;
}
export interface LightConfigInternal {
entity: string;
name?: string;
}
export interface LightPresetManagerConfigInternal {
group: string;
title?: string;
lights: string[];
lights: LightConfigInternal[];
temperatures: TemperaturesConfig;
presets: number;
}
+73 -9
View File
@@ -1,9 +1,12 @@
import type {
HassEntity,
LightState,
LightConfig,
LightConfigInternal,
LightPresetManagerConfig,
LightPresetManagerConfigInternal,
TemperaturesConfig,
TemperatureType,
} from "./types";
// Defaults
@@ -15,6 +18,18 @@ export const DEFAULT_TEMPERATURES: TemperaturesConfig = {
export const DEFAULT_PRESETS = 4;
/**
* Normalizes light config (string or object) to internal format
*/
function normalizeLightConfig(
light: string | LightConfig
): LightConfigInternal {
if (typeof light === "string") {
return { entity: light };
}
return { entity: light.entity, name: light.name };
}
/**
* Validates user config and applies defaults
*/
@@ -29,11 +44,17 @@ export function validateConfig(
throw new Error(`Config error: "${config.group}" is not a light.* entity`);
}
const lights: LightConfigInternal[] = [];
if (config.lights) {
for (const light of config.lights) {
if (!light.startsWith("light.")) {
throw new Error(`Config error: "${light}" is not a light.* entity`);
const normalized = normalizeLightConfig(light);
if (!normalized.entity.startsWith("light.")) {
throw new Error(
`Config error: "${normalized.entity}" is not a light.* entity`
);
}
lights.push(normalized);
}
}
@@ -47,7 +68,7 @@ export function validateConfig(
return {
group: config.group,
title: config.title,
lights: config.lights || [],
lights,
temperatures: {
warm: config.temperatures?.warm || DEFAULT_TEMPERATURES.warm,
neutral: config.temperatures?.neutral || DEFAULT_TEMPERATURES.neutral,
@@ -72,8 +93,13 @@ export const getBrightnessPercent = (entity?: HassEntity): number => {
export const percentToBrightness = (percent: number): number =>
Math.round((percent / 100) * 255);
export const getEntityName = (entity?: HassEntity): string =>
entity?.attributes.friendly_name || entity?.entity_id || "Unknown";
export const getEntityName = (
entity?: HassEntity,
customName?: string
): string => {
if (customName) return customName;
return entity?.attributes.friendly_name || entity?.entity_id || "Unknown";
};
// Temperature helpers
export const kelvinToMireds = (kelvin: number): number =>
@@ -114,15 +140,53 @@ export function captureLightState(entity: HassEntity): LightState {
*/
export function getLightsFromGroup(
groupEntity: HassEntity | undefined,
configLights: string[]
): string[] {
configLights: LightConfigInternal[]
): LightConfigInternal[] {
if (configLights.length > 0) {
return configLights;
}
if (groupEntity?.attributes.entity_id) {
return groupEntity.attributes.entity_id;
return groupEntity.attributes.entity_id.map((entity) => ({ entity }));
}
return groupEntity ? [groupEntity.entity_id] : [];
return groupEntity ? [{ entity: groupEntity.entity_id }] : [];
}
/**
* Determines the current temperature zone based on color_temp value
* Returns 'warm' | 'neutral' | 'cold' | null
*/
export function getCurrentTempZone(
entity: HassEntity | undefined,
temperatures: TemperaturesConfig
): TemperatureType | null {
if (!entity || entity.state !== "on") return null;
const colorTemp = entity.attributes.color_temp;
if (colorTemp === undefined) return null;
// Calculate midpoints between zones
const warmNeutralMid = (temperatures.warm + temperatures.neutral) / 2;
const neutralColdMid = (temperatures.neutral + temperatures.cold) / 2;
if (colorTemp >= warmNeutralMid) return "warm";
if (colorTemp <= neutralColdMid) return "cold";
return "neutral";
}
/**
* Gets the color for a temperature zone
*/
export function getTempColor(zone: TemperatureType | null): string {
switch (zone) {
case "warm":
return "var(--lpm-temp-warm-color, #ff9800)";
case "neutral":
return "var(--lpm-temp-neutral-color, #9e9e9e)";
case "cold":
return "var(--lpm-temp-cold-color, #2196f3)";
default:
return "var(--disabled-text-color, #999)";
}
}
+1 -1
View File
@@ -1 +1 @@
{"pid": 68, "version": 1, "ha_version": "2025.12.5", "start_ts": 1767191926.8295555}
{"pid": 67, "version": 1, "ha_version": "2025.12.5", "start_ts": 1767194043.955861}
+170 -165
View File
@@ -1,166 +1,171 @@
2025-12-31 15:36:12.964 INFO (MainThread) [homeassistant.setup] Setting up system_log
2025-12-31 15:36:12.988 INFO (MainThread) [homeassistant.setup] Setup of domain http took 0.02 seconds
2025-12-31 15:36:12.988 INFO (MainThread) [homeassistant.setup] Setup of domain logger took 0.02 seconds
2025-12-31 15:36:12.988 INFO (MainThread) [homeassistant.setup] Setting up websocket_api
2025-12-31 15:36:12.988 INFO (MainThread) [homeassistant.setup] Setup of domain websocket_api took 0.00 seconds
2025-12-31 15:36:12.988 INFO (MainThread) [homeassistant.setup] Setup of domain system_log took 0.02 seconds
2025-12-31 15:36:12.992 INFO (MainThread) [homeassistant.setup] Setting up network
2025-12-31 15:36:12.993 INFO (MainThread) [homeassistant.setup] Setup of domain network took 0.00 seconds
2025-12-31 15:36:12.993 INFO (MainThread) [homeassistant.bootstrap] Setting up stage labs: {'labs'}; already set up: {}
2025-12-31 16:08:23.624 INFO (MainThread) [homeassistant.setup] Setup of domain system_log took 0.02 seconds
2025-12-31 16:08:23.624 INFO (MainThread) [homeassistant.setup] Setup of domain http took 0.02 seconds
2025-12-31 16:08:23.624 INFO (MainThread) [homeassistant.setup] Setup of domain logger took 0.02 seconds
2025-12-31 16:08:23.624 INFO (MainThread) [homeassistant.setup] Setting up websocket_api
2025-12-31 16:08:23.624 INFO (MainThread) [homeassistant.setup] Setup of domain websocket_api took 0.00 seconds
2025-12-31 16:08:23.630 INFO (MainThread) [homeassistant.setup] Setting up network
2025-12-31 16:08:23.631 INFO (MainThread) [homeassistant.setup] Setup of domain network took 0.00 seconds
2025-12-31 16:08:23.631 INFO (MainThread) [homeassistant.bootstrap] Setting up stage labs: {'labs'}; already set up: {}
Dependencies: {}; already set up: {}
2025-12-31 15:36:12.994 INFO (MainThread) [homeassistant.setup] Setting up labs
2025-12-31 15:36:12.994 INFO (MainThread) [homeassistant.setup] Setup of domain labs took 0.00 seconds
2025-12-31 15:36:12.994 INFO (MainThread) [homeassistant.bootstrap] Setting up stage frontend: {'frontend'}; already set up: {}
Dependencies: {'lovelace', 'device_automation', 'repairs', 'api', 'config', 'diagnostics', 'onboarding', 'auth', 'search', 'file_upload'}; already set up: {'http', 'system_log', 'websocket_api'}
2025-12-31 15:36:12.994 INFO (MainThread) [homeassistant.setup] Setting up auth
2025-12-31 15:36:12.994 INFO (MainThread) [homeassistant.setup] Setup of domain auth took 0.00 seconds
2025-12-31 15:36:12.994 INFO (MainThread) [homeassistant.setup] Setting up onboarding
2025-12-31 15:36:12.994 INFO (MainThread) [homeassistant.setup] Setting up device_automation
2025-12-31 15:36:12.994 INFO (MainThread) [homeassistant.setup] Setup of domain device_automation took 0.00 seconds
2025-12-31 15:36:12.994 INFO (MainThread) [homeassistant.setup] Setting up api
2025-12-31 15:36:12.995 INFO (MainThread) [homeassistant.setup] Setup of domain api took 0.00 seconds
2025-12-31 15:36:12.995 INFO (MainThread) [homeassistant.setup] Setting up config
2025-12-31 15:36:12.996 INFO (MainThread) [homeassistant.setup] Setup of domain config took 0.00 seconds
2025-12-31 15:36:12.996 INFO (MainThread) [homeassistant.setup] Setting up diagnostics
2025-12-31 15:36:12.997 INFO (MainThread) [homeassistant.setup] Setup of domain diagnostics took 0.00 seconds
2025-12-31 15:36:12.997 INFO (MainThread) [homeassistant.setup] Setting up file_upload
2025-12-31 15:36:12.997 INFO (MainThread) [homeassistant.setup] Setup of domain file_upload took 0.00 seconds
2025-12-31 15:36:12.997 INFO (MainThread) [homeassistant.setup] Setting up repairs
2025-12-31 15:36:12.997 INFO (MainThread) [homeassistant.setup] Setup of domain repairs took 0.00 seconds
2025-12-31 15:36:12.997 INFO (MainThread) [homeassistant.setup] Setting up search
2025-12-31 15:36:12.997 INFO (MainThread) [homeassistant.setup] Setup of domain search took 0.00 seconds
2025-12-31 15:36:13.001 INFO (MainThread) [homeassistant.setup] Setup of domain onboarding took 0.01 seconds
2025-12-31 15:36:13.001 INFO (MainThread) [homeassistant.setup] Setting up lovelace
2025-12-31 15:36:13.002 INFO (MainThread) [homeassistant.setup] Setup of domain lovelace took 0.00 seconds
2025-12-31 15:36:13.006 INFO (MainThread) [homeassistant.setup] Setting up frontend
2025-12-31 15:36:13.013 INFO (MainThread) [homeassistant.setup] Setup of domain frontend took 0.01 seconds
2025-12-31 15:36:13.013 INFO (MainThread) [homeassistant.bootstrap] Nothing to set up in stage recorder: {'recorder'}
2025-12-31 15:36:13.013 INFO (MainThread) [homeassistant.bootstrap] Nothing to set up in stage debugger: {'debugpy'}
2025-12-31 15:36:13.013 INFO (MainThread) [homeassistant.bootstrap] Nothing to set up in stage zeroconf: {'zeroconf'}
2025-12-31 15:36:13.013 INFO (MainThread) [homeassistant.bootstrap] Nothing to set up in stage 1: {'dhcp', 'mqtt_eventstream', 'usb', 'ssdp', 'bluetooth', 'cloud', 'hassio'}
2025-12-31 15:36:13.013 INFO (MainThread) [homeassistant.bootstrap] Setting up stage 2: {'radio_browser', 'timer', 'tag', 'backup', 'input_boolean', 'shopping_list', 'hardware', 'input_datetime', 'google_translate', 'input_select', 'application_credentials', 'mqtt', 'input_button', 'person', 'scene', 'zone', 'input_text', 'input_number', 'system_health', 'analytics', 'automation', 'counter', 'schedule', 'script'}; already set up: {'http', 'homeassistant', 'api', 'frontend', 'config', 'network', 'labs', 'logger'}
Dependencies: {'blueprint', 'image_upload', 'trace'}; already set up: {'http', 'device_automation', 'api', 'auth', 'websocket_api', 'file_upload'}
2025-12-31 15:36:13.014 INFO (MainThread) [homeassistant.setup] Setting up scene
2025-12-31 15:36:13.014 INFO (MainThread) [homeassistant.components.scene] Setting up homeassistant.scene
2025-12-31 15:36:13.014 INFO (MainThread) [homeassistant.components.scene] Setting up homeassistant.scene
2025-12-31 15:36:13.015 INFO (MainThread) [homeassistant.components.scene] Setting up homeassistant.scene
2025-12-31 15:36:13.015 INFO (MainThread) [homeassistant.setup] Setup of domain scene took 0.00 seconds
2025-12-31 15:36:13.017 INFO (MainThread) [homeassistant.setup] Setting up zone
2025-12-31 15:36:13.018 INFO (MainThread) [homeassistant.setup] Setup of domain zone took 0.00 seconds
2025-12-31 15:36:13.018 INFO (MainThread) [homeassistant.setup] Setting up trace
2025-12-31 15:36:13.018 INFO (MainThread) [homeassistant.setup] Setup of domain trace took 0.00 seconds
2025-12-31 15:36:13.018 INFO (MainThread) [homeassistant.setup] Setting up input_number
2025-12-31 15:36:13.019 INFO (MainThread) [homeassistant.setup] Setup of domain input_number took 0.00 seconds
2025-12-31 15:36:13.019 INFO (MainThread) [homeassistant.setup] Setting up system_health
2025-12-31 15:36:13.019 INFO (MainThread) [homeassistant.setup] Setup of domain system_health took 0.00 seconds
2025-12-31 15:36:13.019 INFO (MainThread) [homeassistant.setup] Setting up blueprint
2025-12-31 15:36:13.019 INFO (MainThread) [homeassistant.setup] Setup of domain blueprint took 0.00 seconds
2025-12-31 15:36:13.019 INFO (MainThread) [homeassistant.setup] Setting up automation
2025-12-31 15:36:13.020 INFO (MainThread) [homeassistant.setup] Setup of domain automation took 0.00 seconds
2025-12-31 15:36:13.020 INFO (MainThread) [homeassistant.setup] Setting up script
2025-12-31 15:36:13.020 INFO (MainThread) [homeassistant.setup] Setup of domain script took 0.00 seconds
2025-12-31 15:36:13.021 INFO (MainThread) [homeassistant.components.http] Now listening on port 8123
2025-12-31 15:36:13.021 INFO (MainThread) [homeassistant.setup] Setup of domain http took 0.01 seconds
2025-12-31 15:36:13.024 INFO (MainThread) [homeassistant.setup] Setting up input_button
2025-12-31 15:36:13.024 INFO (MainThread) [homeassistant.setup] Setup of domain input_button took 0.00 seconds
2025-12-31 15:36:13.026 INFO (MainThread) [homeassistant.setup] Setting up timer
2025-12-31 15:36:13.027 INFO (MainThread) [homeassistant.setup] Setup of domain timer took 0.00 seconds
2025-12-31 15:36:13.033 INFO (MainThread) [homeassistant.setup] Setting up tag
2025-12-31 15:36:13.033 INFO (MainThread) [homeassistant.setup] Setup of domain tag took 0.00 seconds
2025-12-31 15:36:13.035 INFO (MainThread) [homeassistant.setup] Setting up input_text
2025-12-31 15:36:13.036 INFO (MainThread) [homeassistant.setup] Setup of domain input_text took 0.00 seconds
2025-12-31 15:36:13.037 INFO (MainThread) [homeassistant.setup] Setting up image_upload
2025-12-31 15:36:13.038 INFO (MainThread) [homeassistant.setup] Setup of domain image_upload took 0.00 seconds
2025-12-31 15:36:13.038 INFO (MainThread) [homeassistant.setup] Setting up person
2025-12-31 15:36:13.038 INFO (MainThread) [homeassistant.setup] Setup of domain person took 0.00 seconds
2025-12-31 15:36:13.040 INFO (MainThread) [homeassistant.setup] Setting up input_boolean
2025-12-31 15:36:13.040 INFO (MainThread) [homeassistant.setup] Setup of domain input_boolean took 0.00 seconds
2025-12-31 15:36:13.047 INFO (MainThread) [homeassistant.setup] Setting up shopping_list
2025-12-31 15:36:13.047 INFO (MainThread) [homeassistant.setup] Setup of domain shopping_list took 0.00 seconds
2025-12-31 15:36:13.049 INFO (MainThread) [homeassistant.setup] Setting up input_datetime
2025-12-31 15:36:13.049 INFO (MainThread) [homeassistant.setup] Setup of domain input_datetime took 0.00 seconds
2025-12-31 15:36:13.055 INFO (MainThread) [homeassistant.setup] Setting up input_select
2025-12-31 15:36:13.055 INFO (MainThread) [homeassistant.setup] Setup of domain input_select took 0.00 seconds
2025-12-31 15:36:13.055 INFO (MainThread) [homeassistant.setup] Setting up counter
2025-12-31 15:36:13.056 INFO (MainThread) [homeassistant.setup] Setup of domain counter took 0.00 seconds
2025-12-31 15:36:13.060 INFO (MainThread) [homeassistant.setup] Setting up schedule
2025-12-31 15:36:13.060 INFO (MainThread) [homeassistant.setup] Setup of domain schedule took 0.00 seconds
2025-12-31 15:36:13.062 INFO (MainThread) [homeassistant.setup] Setting up application_credentials
2025-12-31 15:36:13.062 INFO (MainThread) [homeassistant.setup] Setup of domain application_credentials took 0.00 seconds
2025-12-31 15:36:13.127 INFO (MainThread) [homeassistant.setup] Setting up backup
2025-12-31 15:36:13.128 INFO (MainThread) [homeassistant.setup] Setup of domain backup took 0.00 seconds
2025-12-31 15:36:13.130 INFO (MainThread) [homeassistant.setup] Setting up radio_browser
2025-12-31 15:36:13.131 INFO (MainThread) [homeassistant.setup] Setup of domain radio_browser took 0.00 seconds
2025-12-31 15:36:13.137 INFO (MainThread) [homeassistant.setup] Setting up todo
2025-12-31 15:36:13.138 INFO (MainThread) [homeassistant.setup] Setup of domain todo took 0.00 seconds
2025-12-31 15:36:13.139 INFO (MainThread) [homeassistant.components.todo] Setting up shopping_list.todo
2025-12-31 15:36:13.142 INFO (MainThread) [homeassistant.setup] Setting up hardware
2025-12-31 15:36:13.154 INFO (MainThread) [homeassistant.setup] Setup of domain hardware took 0.01 seconds
2025-12-31 15:36:13.166 INFO (MainThread) [homeassistant.setup] Setting up google_translate
2025-12-31 15:36:13.166 INFO (MainThread) [homeassistant.setup] Setup of domain google_translate took 0.00 seconds
2025-12-31 15:36:13.172 INFO (MainThread) [homeassistant.setup] Setting up analytics
2025-12-31 15:36:13.173 INFO (MainThread) [homeassistant.setup] Setup of domain analytics took 0.00 seconds
2025-12-31 15:36:13.192 INFO (MainThread) [homeassistant.setup] Setting up mqtt
2025-12-31 15:36:13.192 INFO (MainThread) [homeassistant.setup] Setup of domain mqtt took 0.00 seconds
2025-12-31 15:36:13.196 INFO (MainThread) [homeassistant.setup] Setting up ffmpeg
2025-12-31 15:36:13.197 INFO (MainThread) [homeassistant.setup] Setup of domain ffmpeg took 0.00 seconds
2025-12-31 15:36:13.197 INFO (MainThread) [homeassistant.setup] Setting up tts
2025-12-31 15:36:13.199 INFO (MainThread) [homeassistant.setup] Setting up event
2025-12-31 15:36:13.199 INFO (MainThread) [homeassistant.setup] Setup of domain event took 0.00 seconds
2025-12-31 15:36:13.199 INFO (MainThread) [homeassistant.setup] Setting up sensor
2025-12-31 15:36:13.199 INFO (MainThread) [homeassistant.setup] Setup of domain sensor took 0.00 seconds
2025-12-31 15:36:13.200 INFO (MainThread) [homeassistant.components.event] Setting up backup.event
2025-12-31 15:36:13.200 INFO (MainThread) [homeassistant.components.sensor] Setting up backup.sensor
2025-12-31 15:36:13.204 INFO (MainThread) [homeassistant.setup] Setup of domain tts took 0.01 seconds
2025-12-31 15:36:13.204 INFO (MainThread) [homeassistant.components.tts] Setting up google_translate.tts
2025-12-31 15:36:14.105 INFO (MainThread) [homeassistant.setup] Setting up light
2025-12-31 15:36:14.106 INFO (MainThread) [homeassistant.setup] Setup of domain light took 0.00 seconds
2025-12-31 15:36:14.106 INFO (MainThread) [homeassistant.setup] Setting up switch
2025-12-31 15:36:14.106 INFO (MainThread) [homeassistant.setup] Setup of domain switch took 0.00 seconds
2025-12-31 15:36:14.107 INFO (MainThread) [homeassistant.setup] Setting up update
2025-12-31 15:36:14.107 INFO (MainThread) [homeassistant.setup] Setup of domain update took 0.00 seconds
2025-12-31 15:36:14.107 INFO (MainThread) [homeassistant.setup] Setting up select
2025-12-31 15:36:14.107 INFO (MainThread) [homeassistant.setup] Setup of domain select took 0.00 seconds
2025-12-31 15:36:14.107 INFO (MainThread) [homeassistant.setup] Setting up button
2025-12-31 15:36:14.107 INFO (MainThread) [homeassistant.setup] Setup of domain button took 0.00 seconds
2025-12-31 15:36:14.107 INFO (MainThread) [homeassistant.setup] Setting up binary_sensor
2025-12-31 15:36:14.108 INFO (MainThread) [homeassistant.setup] Setup of domain binary_sensor took 0.00 seconds
2025-12-31 15:36:14.111 INFO (MainThread) [homeassistant.components.scene] Setting up mqtt.scene
2025-12-31 15:36:14.111 INFO (MainThread) [homeassistant.components.light] Setting up mqtt.light
2025-12-31 15:36:14.111 INFO (MainThread) [homeassistant.components.switch] Setting up mqtt.switch
2025-12-31 15:36:14.111 INFO (MainThread) [homeassistant.components.update] Setting up mqtt.update
2025-12-31 15:36:14.111 INFO (MainThread) [homeassistant.components.sensor] Setting up mqtt.sensor
2025-12-31 15:36:14.111 INFO (MainThread) [homeassistant.components.select] Setting up mqtt.select
2025-12-31 15:36:14.111 INFO (MainThread) [homeassistant.components.button] Setting up mqtt.button
2025-12-31 15:36:14.111 INFO (MainThread) [homeassistant.components.binary_sensor] Setting up mqtt.binary_sensor
2025-12-31 15:36:14.113 INFO (MainThread) [homeassistant.bootstrap] Home Assistant initialized in 1.69s
2025-12-31 15:36:14.113 INFO (MainThread) [homeassistant.core] Starting Home Assistant 2025.12.5
2025-12-31 15:36:14.729 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_asleep_screens_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_asleep_screens"` option with `"default_entity_id": "button.WARMACHINE-PAPA_asleep_screens"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:14.730 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_awake_screens_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_awake_screens"` option with `"default_entity_id": "button.WARMACHINE-PAPA_awake_screens"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:14.731 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_veille_prolonge_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_veille_prolonge"` option with `"default_entity_id": "button.WARMACHINE-PAPA_veille_prolonge"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:14.732 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_play_pause_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_play_pause"` option with `"default_entity_id": "button.WARMACHINE-PAPA_play_pause"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:14.732 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_volume_up_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_volume_up"` option with `"default_entity_id": "button.WARMACHINE-PAPA_volume_up"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:14.733 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_volume_down_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_volume_down"` option with `"default_entity_id": "button.WARMACHINE-PAPA_volume_down"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:14.734 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_touche_right_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_touche_right"` option with `"default_entity_id": "button.WARMACHINE-PAPA_touche_right"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:14.735 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_touche_left_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_touche_left"` option with `"default_entity_id": "button.WARMACHINE-PAPA_touche_left"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:14.735 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_touche_up_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_touche_up"` option with `"default_entity_id": "button.WARMACHINE-PAPA_touche_up"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:14.736 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_touche_down_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_touche_down"` option with `"default_entity_id": "button.WARMACHINE-PAPA_touche_down"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:14.737 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_alt_tab_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_alt_tab"` option with `"default_entity_id": "button.WARMACHINE-PAPA_alt_tab"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:14.738 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_mute_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_mute"` option with `"default_entity_id": "button.WARMACHINE-PAPA_mute"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:14.738 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_veille_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_veille"` option with `"default_entity_id": "button.WARMACHINE-PAPA_veille"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:15.090 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_chargecpu_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_chargecpu"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_chargecpu"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:15.092 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_chargegpu_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_chargegpu"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_chargegpu"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:15.093 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_temp_gpu_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_temp_gpu"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_temp_gpu"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:15.094 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_screen_state_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_screen_state"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_screen_state"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:15.095 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_batterie_charge_status_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_batterie_charge_status"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_batterie_charge_status"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:15.096 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_batterie_full_charge_lifetime_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_batterie_full_charge_lifetime"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_batterie_full_charge_lifetime"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:15.097 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_batterie_charge_remaining_percentage_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_batterie_charge_remaining_percentage"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_batterie_charge_remaining_percentage"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:15.099 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_batterie_charge_remaining_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_batterie_charge_remaining"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_batterie_charge_remaining"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:15.100 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_batterie_powerline_status_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_batterie_powerline_status"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_batterie_powerline_status"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 15:36:15.137 INFO (MainThread) [homeassistant.components.websocket_api.http.connection] [140359807808864] Received unknown command: recorder/info
2025-12-31 15:36:20.738 INFO (MainThread) [homeassistant.components.mqtt.client] MQTT client initialized, birth message sent
2025-12-31 15:36:21.601 INFO (MainThread) [homeassistant.components.websocket_api.http.connection] [140359810301632] Received unknown command: recorder/info
2025-12-31 15:36:26.253 INFO (MainThread) [homeassistant.components.websocket_api.http.connection] [140359807802944] Received unknown command: recorder/info
2025-12-31 15:37:25.355 WARNING (MainThread) [homeassistant.components.light] Got `color_temp` argument in `turn_on` service, which is deprecated and will break in Home Assistant 2026.1, please use `color_temp_kelvin` argument
2025-12-31 15:37:26.839 WARNING (MainThread) [homeassistant.components.light] Got `color_temp` argument in `turn_on` service, which is deprecated and will break in Home Assistant 2026.1, please use `color_temp_kelvin` argument
2025-12-31 15:37:27.635 WARNING (MainThread) [homeassistant.components.light] Got `color_temp` argument in `turn_on` service, which is deprecated and will break in Home Assistant 2026.1, please use `color_temp_kelvin` argument
2025-12-31 16:08:23.631 INFO (MainThread) [homeassistant.setup] Setting up labs
2025-12-31 16:08:23.631 INFO (MainThread) [homeassistant.setup] Setup of domain labs took 0.00 seconds
2025-12-31 16:08:23.631 INFO (MainThread) [homeassistant.bootstrap] Setting up stage frontend: {'frontend'}; already set up: {}
Dependencies: {'onboarding', 'file_upload', 'auth', 'diagnostics', 'device_automation', 'config', 'lovelace', 'api', 'repairs', 'search'}; already set up: {'websocket_api', 'system_log', 'http'}
2025-12-31 16:08:23.631 INFO (MainThread) [homeassistant.setup] Setting up auth
2025-12-31 16:08:23.632 INFO (MainThread) [homeassistant.setup] Setup of domain auth took 0.00 seconds
2025-12-31 16:08:23.632 INFO (MainThread) [homeassistant.setup] Setting up onboarding
2025-12-31 16:08:23.632 INFO (MainThread) [homeassistant.setup] Setup of domain onboarding took 0.00 seconds
2025-12-31 16:08:23.632 INFO (MainThread) [homeassistant.setup] Setting up file_upload
2025-12-31 16:08:23.632 INFO (MainThread) [homeassistant.setup] Setup of domain file_upload took 0.00 seconds
2025-12-31 16:08:23.632 INFO (MainThread) [homeassistant.setup] Setting up diagnostics
2025-12-31 16:08:23.632 INFO (MainThread) [homeassistant.setup] Setup of domain diagnostics took 0.00 seconds
2025-12-31 16:08:23.632 INFO (MainThread) [homeassistant.setup] Setting up api
2025-12-31 16:08:23.633 INFO (MainThread) [homeassistant.setup] Setup of domain api took 0.00 seconds
2025-12-31 16:08:23.633 INFO (MainThread) [homeassistant.setup] Setting up config
2025-12-31 16:08:23.635 INFO (MainThread) [homeassistant.setup] Setup of domain config took 0.00 seconds
2025-12-31 16:08:23.635 INFO (MainThread) [homeassistant.setup] Setting up device_automation
2025-12-31 16:08:23.635 INFO (MainThread) [homeassistant.setup] Setup of domain device_automation took 0.00 seconds
2025-12-31 16:08:23.635 INFO (MainThread) [homeassistant.setup] Setting up lovelace
2025-12-31 16:08:23.635 INFO (MainThread) [homeassistant.setup] Setting up repairs
2025-12-31 16:08:23.636 INFO (MainThread) [homeassistant.setup] Setup of domain repairs took 0.00 seconds
2025-12-31 16:08:23.636 INFO (MainThread) [homeassistant.setup] Setting up search
2025-12-31 16:08:23.636 INFO (MainThread) [homeassistant.setup] Setup of domain search took 0.00 seconds
2025-12-31 16:08:23.643 INFO (MainThread) [homeassistant.setup] Setup of domain lovelace took 0.01 seconds
2025-12-31 16:08:23.647 INFO (MainThread) [homeassistant.setup] Setting up frontend
2025-12-31 16:08:23.653 INFO (MainThread) [homeassistant.setup] Setup of domain frontend took 0.01 seconds
2025-12-31 16:08:23.653 INFO (MainThread) [homeassistant.bootstrap] Nothing to set up in stage recorder: {'recorder'}
2025-12-31 16:08:23.653 INFO (MainThread) [homeassistant.bootstrap] Nothing to set up in stage debugger: {'debugpy'}
2025-12-31 16:08:23.653 INFO (MainThread) [homeassistant.bootstrap] Nothing to set up in stage zeroconf: {'zeroconf'}
2025-12-31 16:08:23.654 INFO (MainThread) [homeassistant.bootstrap] Nothing to set up in stage 1: {'hassio', 'mqtt_eventstream', 'ssdp', 'dhcp', 'bluetooth', 'usb', 'cloud'}
2025-12-31 16:08:23.654 INFO (MainThread) [homeassistant.bootstrap] Setting up stage 2: {'schedule', 'backup', 'input_button', 'scene', 'application_credentials', 'person', 'system_health', 'script', 'counter', 'mqtt', 'input_select', 'hardware', 'analytics', 'input_number', 'input_boolean', 'shopping_list', 'google_translate', 'tag', 'zone', 'automation', 'timer', 'input_datetime', 'radio_browser', 'input_text'}; already set up: {'labs', 'http', 'frontend', 'config', 'homeassistant', 'api', 'logger', 'network'}
Dependencies: {'trace', 'image_upload', 'blueprint'}; already set up: {'file_upload', 'websocket_api', 'auth', 'device_automation', 'api', 'http'}
2025-12-31 16:08:23.654 INFO (MainThread) [homeassistant.setup] Setting up scene
2025-12-31 16:08:23.654 INFO (MainThread) [homeassistant.components.scene] Setting up homeassistant.scene
2025-12-31 16:08:23.655 INFO (MainThread) [homeassistant.components.scene] Setting up homeassistant.scene
2025-12-31 16:08:23.655 INFO (MainThread) [homeassistant.components.scene] Setting up homeassistant.scene
2025-12-31 16:08:23.655 INFO (MainThread) [homeassistant.setup] Setup of domain scene took 0.00 seconds
2025-12-31 16:08:23.655 INFO (MainThread) [homeassistant.setup] Setting up input_number
2025-12-31 16:08:23.656 INFO (MainThread) [homeassistant.setup] Setup of domain input_number took 0.00 seconds
2025-12-31 16:08:23.656 INFO (MainThread) [homeassistant.setup] Setting up zone
2025-12-31 16:08:23.657 INFO (MainThread) [homeassistant.setup] Setup of domain zone took 0.00 seconds
2025-12-31 16:08:23.657 INFO (MainThread) [homeassistant.setup] Setting up system_health
2025-12-31 16:08:23.657 INFO (MainThread) [homeassistant.setup] Setup of domain system_health took 0.00 seconds
2025-12-31 16:08:23.657 INFO (MainThread) [homeassistant.setup] Setting up blueprint
2025-12-31 16:08:23.657 INFO (MainThread) [homeassistant.setup] Setup of domain blueprint took 0.00 seconds
2025-12-31 16:08:23.657 INFO (MainThread) [homeassistant.setup] Setting up trace
2025-12-31 16:08:23.657 INFO (MainThread) [homeassistant.setup] Setup of domain trace took 0.00 seconds
2025-12-31 16:08:23.657 INFO (MainThread) [homeassistant.setup] Setting up script
2025-12-31 16:08:23.657 INFO (MainThread) [homeassistant.setup] Setup of domain script took 0.00 seconds
2025-12-31 16:08:23.658 INFO (MainThread) [homeassistant.setup] Setting up automation
2025-12-31 16:08:23.658 INFO (MainThread) [homeassistant.setup] Setup of domain automation took 0.00 seconds
2025-12-31 16:08:23.661 INFO (MainThread) [homeassistant.components.http] Now listening on port 8123
2025-12-31 16:08:23.661 INFO (MainThread) [homeassistant.setup] Setup of domain http took 0.01 seconds
2025-12-31 16:08:23.662 INFO (MainThread) [homeassistant.setup] Setting up input_boolean
2025-12-31 16:08:23.663 INFO (MainThread) [homeassistant.setup] Setup of domain input_boolean took 0.00 seconds
2025-12-31 16:08:23.666 INFO (MainThread) [homeassistant.setup] Setting up schedule
2025-12-31 16:08:23.667 INFO (MainThread) [homeassistant.setup] Setup of domain schedule took 0.00 seconds
2025-12-31 16:08:23.676 INFO (MainThread) [homeassistant.setup] Setting up shopping_list
2025-12-31 16:08:23.676 INFO (MainThread) [homeassistant.setup] Setup of domain shopping_list took 0.00 seconds
2025-12-31 16:08:23.676 INFO (MainThread) [homeassistant.setup] Setting up input_button
2025-12-31 16:08:23.676 INFO (MainThread) [homeassistant.setup] Setup of domain input_button took 0.00 seconds
2025-12-31 16:08:23.680 INFO (MainThread) [homeassistant.setup] Setting up tag
2025-12-31 16:08:23.680 INFO (MainThread) [homeassistant.setup] Setup of domain tag took 0.00 seconds
2025-12-31 16:08:23.683 INFO (MainThread) [homeassistant.setup] Setting up application_credentials
2025-12-31 16:08:23.683 INFO (MainThread) [homeassistant.setup] Setup of domain application_credentials took 0.00 seconds
2025-12-31 16:08:23.686 INFO (MainThread) [homeassistant.setup] Setting up counter
2025-12-31 16:08:23.687 INFO (MainThread) [homeassistant.setup] Setup of domain counter took 0.00 seconds
2025-12-31 16:08:23.689 INFO (MainThread) [homeassistant.setup] Setting up timer
2025-12-31 16:08:23.690 INFO (MainThread) [homeassistant.setup] Setup of domain timer took 0.00 seconds
2025-12-31 16:08:23.694 INFO (MainThread) [homeassistant.setup] Setting up input_select
2025-12-31 16:08:23.695 INFO (MainThread) [homeassistant.setup] Setup of domain input_select took 0.00 seconds
2025-12-31 16:08:23.697 INFO (MainThread) [homeassistant.setup] Setting up input_datetime
2025-12-31 16:08:23.697 INFO (MainThread) [homeassistant.setup] Setup of domain input_datetime took 0.00 seconds
2025-12-31 16:08:23.699 INFO (MainThread) [homeassistant.setup] Setting up input_text
2025-12-31 16:08:23.700 INFO (MainThread) [homeassistant.setup] Setup of domain input_text took 0.00 seconds
2025-12-31 16:08:23.702 INFO (MainThread) [homeassistant.setup] Setting up image_upload
2025-12-31 16:08:23.702 INFO (MainThread) [homeassistant.setup] Setup of domain image_upload took 0.00 seconds
2025-12-31 16:08:23.702 INFO (MainThread) [homeassistant.setup] Setting up person
2025-12-31 16:08:23.703 INFO (MainThread) [homeassistant.setup] Setup of domain person took 0.00 seconds
2025-12-31 16:08:23.706 INFO (MainThread) [homeassistant.setup] Setting up todo
2025-12-31 16:08:23.708 INFO (MainThread) [homeassistant.setup] Setup of domain todo took 0.00 seconds
2025-12-31 16:08:23.710 INFO (MainThread) [homeassistant.components.todo] Setting up shopping_list.todo
2025-12-31 16:08:23.722 INFO (MainThread) [homeassistant.setup] Setting up backup
2025-12-31 16:08:23.726 INFO (MainThread) [homeassistant.setup] Setup of domain backup took 0.00 seconds
2025-12-31 16:08:23.735 INFO (MainThread) [homeassistant.setup] Setting up google_translate
2025-12-31 16:08:23.735 INFO (MainThread) [homeassistant.setup] Setup of domain google_translate took 0.00 seconds
2025-12-31 16:08:23.795 INFO (MainThread) [homeassistant.setup] Setting up radio_browser
2025-12-31 16:08:23.795 INFO (MainThread) [homeassistant.setup] Setup of domain radio_browser took 0.00 seconds
2025-12-31 16:08:23.800 INFO (MainThread) [homeassistant.setup] Setting up hardware
2025-12-31 16:08:23.815 INFO (MainThread) [homeassistant.setup] Setting up analytics
2025-12-31 16:08:23.815 INFO (MainThread) [homeassistant.setup] Setup of domain analytics took 0.00 seconds
2025-12-31 16:08:23.815 INFO (MainThread) [homeassistant.setup] Setup of domain hardware took 0.02 seconds
2025-12-31 16:08:23.838 INFO (MainThread) [homeassistant.setup] Setting up mqtt
2025-12-31 16:08:23.839 INFO (MainThread) [homeassistant.setup] Setup of domain mqtt took 0.00 seconds
2025-12-31 16:08:23.844 INFO (MainThread) [homeassistant.setup] Setting up ffmpeg
2025-12-31 16:08:23.848 INFO (MainThread) [homeassistant.setup] Setting up event
2025-12-31 16:08:23.848 INFO (MainThread) [homeassistant.setup] Setup of domain event took 0.00 seconds
2025-12-31 16:08:23.848 INFO (MainThread) [homeassistant.setup] Setting up sensor
2025-12-31 16:08:23.848 INFO (MainThread) [homeassistant.setup] Setup of domain sensor took 0.00 seconds
2025-12-31 16:08:23.848 INFO (MainThread) [homeassistant.setup] Setup of domain ffmpeg took 0.00 seconds
2025-12-31 16:08:23.848 INFO (MainThread) [homeassistant.setup] Setting up tts
2025-12-31 16:08:23.849 INFO (MainThread) [homeassistant.components.event] Setting up backup.event
2025-12-31 16:08:23.850 INFO (MainThread) [homeassistant.components.sensor] Setting up backup.sensor
2025-12-31 16:08:23.854 INFO (MainThread) [homeassistant.setup] Setup of domain tts took 0.01 seconds
2025-12-31 16:08:23.855 INFO (MainThread) [homeassistant.components.tts] Setting up google_translate.tts
2025-12-31 16:08:24.751 INFO (MainThread) [homeassistant.setup] Setting up binary_sensor
2025-12-31 16:08:24.751 INFO (MainThread) [homeassistant.setup] Setup of domain binary_sensor took 0.00 seconds
2025-12-31 16:08:24.752 INFO (MainThread) [homeassistant.setup] Setting up button
2025-12-31 16:08:24.752 INFO (MainThread) [homeassistant.setup] Setup of domain button took 0.00 seconds
2025-12-31 16:08:24.752 INFO (MainThread) [homeassistant.setup] Setting up update
2025-12-31 16:08:24.753 INFO (MainThread) [homeassistant.setup] Setup of domain update took 0.00 seconds
2025-12-31 16:08:24.753 INFO (MainThread) [homeassistant.setup] Setting up light
2025-12-31 16:08:24.754 INFO (MainThread) [homeassistant.setup] Setup of domain light took 0.00 seconds
2025-12-31 16:08:24.754 INFO (MainThread) [homeassistant.setup] Setting up select
2025-12-31 16:08:24.754 INFO (MainThread) [homeassistant.setup] Setup of domain select took 0.00 seconds
2025-12-31 16:08:24.754 INFO (MainThread) [homeassistant.setup] Setting up switch
2025-12-31 16:08:24.754 INFO (MainThread) [homeassistant.setup] Setup of domain switch took 0.00 seconds
2025-12-31 16:08:24.757 INFO (MainThread) [homeassistant.components.binary_sensor] Setting up mqtt.binary_sensor
2025-12-31 16:08:24.757 INFO (MainThread) [homeassistant.components.button] Setting up mqtt.button
2025-12-31 16:08:24.757 INFO (MainThread) [homeassistant.components.scene] Setting up mqtt.scene
2025-12-31 16:08:24.757 INFO (MainThread) [homeassistant.components.update] Setting up mqtt.update
2025-12-31 16:08:24.758 INFO (MainThread) [homeassistant.components.light] Setting up mqtt.light
2025-12-31 16:08:24.758 INFO (MainThread) [homeassistant.components.sensor] Setting up mqtt.sensor
2025-12-31 16:08:24.758 INFO (MainThread) [homeassistant.components.select] Setting up mqtt.select
2025-12-31 16:08:24.758 INFO (MainThread) [homeassistant.components.switch] Setting up mqtt.switch
2025-12-31 16:08:24.760 INFO (MainThread) [homeassistant.bootstrap] Home Assistant initialized in 1.72s
2025-12-31 16:08:24.760 INFO (MainThread) [homeassistant.core] Starting Home Assistant 2025.12.5
2025-12-31 16:08:25.366 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_asleep_screens_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_asleep_screens"` option with `"default_entity_id": "button.WARMACHINE-PAPA_asleep_screens"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.367 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_awake_screens_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_awake_screens"` option with `"default_entity_id": "button.WARMACHINE-PAPA_awake_screens"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.367 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_veille_prolonge_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_veille_prolonge"` option with `"default_entity_id": "button.WARMACHINE-PAPA_veille_prolonge"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.368 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_play_pause_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_play_pause"` option with `"default_entity_id": "button.WARMACHINE-PAPA_play_pause"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.368 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_volume_up_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_volume_up"` option with `"default_entity_id": "button.WARMACHINE-PAPA_volume_up"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.369 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_volume_down_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_volume_down"` option with `"default_entity_id": "button.WARMACHINE-PAPA_volume_down"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.369 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_touche_right_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_touche_right"` option with `"default_entity_id": "button.WARMACHINE-PAPA_touche_right"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.370 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_touche_left_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_touche_left"` option with `"default_entity_id": "button.WARMACHINE-PAPA_touche_left"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.370 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_touche_up_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_touche_up"` option with `"default_entity_id": "button.WARMACHINE-PAPA_touche_up"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.371 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_touche_down_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_touche_down"` option with `"default_entity_id": "button.WARMACHINE-PAPA_touche_down"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.371 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_alt_tab_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_alt_tab"` option with `"default_entity_id": "button.WARMACHINE-PAPA_alt_tab"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.372 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_mute_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_mute"` option with `"default_entity_id": "button.WARMACHINE-PAPA_mute"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.372 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity button.warmachine_papa_veille_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_veille"` option with `"default_entity_id": "button.WARMACHINE-PAPA_veille"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.705 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_chargecpu_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_chargecpu"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_chargecpu"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.706 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_chargegpu_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_chargegpu"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_chargegpu"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.707 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_temp_gpu_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_temp_gpu"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_temp_gpu"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.708 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_screen_state_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_screen_state"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_screen_state"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.709 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_batterie_charge_status_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_batterie_charge_status"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_batterie_charge_status"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.710 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_batterie_full_charge_lifetime_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_batterie_full_charge_lifetime"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_batterie_full_charge_lifetime"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.710 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_batterie_charge_remaining_percentage_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_batterie_charge_remaining_percentage"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_batterie_charge_remaining_percentage"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.716 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_batterie_charge_remaining_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_batterie_charge_remaining"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_batterie_charge_remaining"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.718 WARNING (MainThread) [homeassistant.components.mqtt.entity] The configuration for entity sensor.warmachine_papa_batterie_powerline_status_2 uses the deprecated option `object_id` to set the default entity id. Replace the `"object_id": "WARMACHINE-PAPA_batterie_powerline_status"` option with `"default_entity_id": "sensor.WARMACHINE-PAPA_batterie_powerline_status"` in your published discovery configuration to fix this issue, or contact the maintainer of the integration that published this config to fix this. This will stop working in Home Assistant Core 2026.4
2025-12-31 16:08:25.739 INFO (MainThread) [homeassistant.components.websocket_api.http.connection] [139762306076640] Received unknown command: recorder/info
2025-12-31 16:08:30.537 INFO (MainThread) [homeassistant.components.websocket_api.http.connection] [139762306075520] Received unknown command: recorder/info
2025-12-31 16:08:31.333 INFO (MainThread) [homeassistant.components.mqtt.client] MQTT client initialized, birth message sent
2025-12-31 16:08:34.621 INFO (MainThread) [homeassistant.components.websocket_api.http.connection] [139762310016800] Received unknown command: recorder/info
2025-12-31 16:08:43.114 WARNING (MainThread) [homeassistant.components.light] Got `color_temp` argument in `turn_on` service, which is deprecated and will break in Home Assistant 2026.1, please use `color_temp_kelvin` argument
2025-12-31 16:08:43.930 WARNING (MainThread) [homeassistant.components.light] Got `color_temp` argument in `turn_on` service, which is deprecated and will break in Home Assistant 2026.1, please use `color_temp_kelvin` argument
2025-12-31 16:08:44.713 WARNING (MainThread) [homeassistant.components.light] Got `color_temp` argument in `turn_on` service, which is deprecated and will break in Home Assistant 2026.1, please use `color_temp_kelvin` argument
2025-12-31 16:08:46.210 WARNING (MainThread) [homeassistant.components.light] Got `color_temp` argument in `turn_on` service, which is deprecated and will break in Home Assistant 2026.1, please use `color_temp_kelvin` argument
2025-12-31 16:08:48.977 WARNING (MainThread) [homeassistant.components.light] Got `color_temp` argument in `turn_on` service, which is deprecated and will break in Home Assistant 2026.1, please use `color_temp_kelvin` argument
2025-12-31 16:08:50.208 WARNING (MainThread) [homeassistant.components.light] Got `color_temp` argument in `turn_on` service, which is deprecated and will break in Home Assistant 2026.1, please use `color_temp_kelvin` argument
2025-12-31 16:08:51.939 WARNING (MainThread) [homeassistant.components.light] Got `color_temp` argument in `turn_on` service, which is deprecated and will break in Home Assistant 2026.1, please use `color_temp_kelvin` argument
2025-12-31 16:08:56.919 WARNING (MainThread) [homeassistant.components.light] Got `color_temp` argument in `turn_on` service, which is deprecated and will break in Home Assistant 2026.1, please use `color_temp_kelvin` argument
2025-12-31 16:08:59.106 WARNING (MainThread) [homeassistant.components.light] Got `color_temp` argument in `turn_on` service, which is deprecated and will break in Home Assistant 2026.1, please use `color_temp_kelvin` argument
+315 -91
View File
@@ -604,9 +604,10 @@ function r5(r6) {
// src/styles.ts
var mainStyles = i`
:host {
--lpm-temp-warm-color: #ff9800;
--lpm-temp-neutral-color: #9e9e9e;
--lpm-temp-warm-color: #ffe600ff;
--lpm-temp-neutral-color: #ffffff;
--lpm-temp-cold-color: #2196f3;
--lpm-temp-inactive-color: rgba(255, 255, 255, 0.5);
--lpm-button-radius: 8px;
--lpm-preset-radius: 12px;
--lpm-spacing: 8px;
@@ -735,46 +736,49 @@ var mainStyles = i`
.temp-button {
flex: 1;
padding: 12px var(--lpm-spacing);
padding: 10px var(--lpm-spacing);
border: none;
border-radius: var(--lpm-button-radius);
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
justify-content: center;
gap: 6px;
background: var(--primary-background-color);
color: var(--primary-text-color);
color: var(--lpm-temp-inactive-color);
transition: all var(--lpm-transition);
font-family: inherit;
font-size: 12px;
font-size: 13px;
font-weight: 500;
}
.temp-button:hover {
.temp-button:hover:not(:disabled) {
background: var(--secondary-background-color);
}
.temp-button:active {
transform: scale(0.95);
.temp-button:active:not(:disabled) {
transform: scale(0.97);
}
.temp-button:disabled {
opacity: 0.5;
opacity: 0.4;
cursor: not-allowed;
}
.temp-button.warm {
border-bottom: 3px solid var(--lpm-temp-warm-color);
.temp-button.active.warm {
color: var(--lpm-temp-warm-color);
}
.temp-button.neutral {
border-bottom: 3px solid var(--lpm-temp-neutral-color);
.temp-button.active.neutral {
color: var(--lpm-temp-neutral-color);
}
.temp-button.cold {
border-bottom: 3px solid var(--lpm-temp-cold-color);
.temp-button.active.cold {
color: var(--lpm-temp-cold-color);
}
.temp-button ha-icon {
--mdc-icon-size: 24px;
--mdc-icon-size: 20px;
}
/* Lights Panel */
@@ -901,45 +905,47 @@ var mainStyles = i`
/* Mini Temperature Buttons for individual lights */
.light-temp-buttons {
display: flex;
gap: 4px;
gap: 2px;
}
.light-temp-button {
width: 28px;
height: 28px;
border-radius: 4px;
border-radius: 6px;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
background: var(--primary-background-color);
color: var(--primary-text-color);
color: var(--lpm-temp-inactive-color);
transition: all var(--lpm-transition);
padding: 0;
}
.light-temp-button:hover {
.light-temp-button:hover:not(:disabled) {
background: var(--secondary-background-color);
}
.light-temp-button:active {
.light-temp-button:active:not(:disabled) {
transform: scale(0.95);
}
.light-temp-button:disabled {
opacity: 0.5;
opacity: 0.4;
cursor: not-allowed;
}
.light-temp-button.warm {
border-bottom: 2px solid var(--lpm-temp-warm-color);
.light-temp-button.active.warm {
color: var(--lpm-temp-warm-color);
}
.light-temp-button.neutral {
border-bottom: 2px solid var(--lpm-temp-neutral-color);
.light-temp-button.active.neutral {
color: var(--lpm-temp-neutral-color);
}
.light-temp-button.cold {
border-bottom: 2px solid var(--lpm-temp-cold-color);
.light-temp-button.active.cold {
color: var(--lpm-temp-cold-color);
}
.light-temp-button ha-icon {
@@ -1078,6 +1084,7 @@ var mainStyles = i`
.popup-button:hover {
opacity: 0.9;
}
.popup-button:active {
transform: scale(0.95);
}
@@ -1090,6 +1097,12 @@ var DEFAULT_TEMPERATURES = {
cold: 200
};
var DEFAULT_PRESETS = 4;
function normalizeLightConfig(light) {
if (typeof light === "string") {
return { entity: light };
}
return { entity: light.entity, name: light.name };
}
function validateConfig(config) {
if (!config.group) {
throw new Error('Config error: "group" is required');
@@ -1097,11 +1110,16 @@ function validateConfig(config) {
if (!config.group.startsWith("light.")) {
throw new Error(`Config error: "${config.group}" is not a light.* entity`);
}
const lights = [];
if (config.lights) {
for (const light of config.lights) {
if (!light.startsWith("light.")) {
throw new Error(`Config error: "${light}" is not a light.* entity`);
const normalized = normalizeLightConfig(light);
if (!normalized.entity.startsWith("light.")) {
throw new Error(
`Config error: "${normalized.entity}" is not a light.* entity`
);
}
lights.push(normalized);
}
}
if (config.presets !== void 0 && (config.presets < 1 || config.presets > 4)) {
@@ -1110,7 +1128,7 @@ function validateConfig(config) {
return {
group: config.group,
title: config.title,
lights: config.lights || [],
lights,
temperatures: {
warm: config.temperatures?.warm || DEFAULT_TEMPERATURES.warm,
neutral: config.temperatures?.neutral || DEFAULT_TEMPERATURES.neutral,
@@ -1125,7 +1143,10 @@ var getBrightnessPercent = (entity) => {
const brightness = entity?.attributes.brightness;
return brightness ? Math.round(brightness / 255 * 100) : 0;
};
var getEntityName = (entity) => entity?.attributes.friendly_name || entity?.entity_id || "Unknown";
var getEntityName = (entity, customName) => {
if (customName) return customName;
return entity?.attributes.friendly_name || entity?.entity_id || "Unknown";
};
var supportsColorTemp = (entity) => {
const modes = entity?.attributes.supported_color_modes || [];
return modes.includes("color_temp");
@@ -1135,9 +1156,19 @@ function getLightsFromGroup(groupEntity, configLights) {
return configLights;
}
if (groupEntity?.attributes.entity_id) {
return groupEntity.attributes.entity_id;
return groupEntity.attributes.entity_id.map((entity) => ({ entity }));
}
return groupEntity ? [groupEntity.entity_id] : [];
return groupEntity ? [{ entity: groupEntity.entity_id }] : [];
}
function getCurrentTempZone(entity, temperatures) {
if (!entity || entity.state !== "on") return null;
const colorTemp = entity.attributes.color_temp;
if (colorTemp === void 0) return null;
const warmNeutralMid = (temperatures.warm + temperatures.neutral) / 2;
const neutralColdMid = (temperatures.neutral + temperatures.cold) / 2;
if (colorTemp >= warmNeutralMid) return "warm";
if (colorTemp <= neutralColdMid) return "cold";
return "neutral";
}
// src/locales/en.json
@@ -1225,7 +1256,7 @@ function getTranslations(locale) {
}
// src/editor.ts
var SCHEMA = [
var MAIN_SCHEMA = [
{
name: "group",
required: true,
@@ -1241,15 +1272,6 @@ var SCHEMA = [
text: {}
}
},
{
name: "lights",
selector: {
entity: {
domain: "light",
multiple: true
}
}
},
{
name: "presets",
selector: {
@@ -1268,7 +1290,6 @@ var LightPresetManagerEditor = class extends i4 {
const labels = {
group: "Group (required)",
title: "Title",
lights: "Individual Lights",
presets: "Number of Presets (1-4)"
};
return labels[schema.name] || schema.name;
@@ -1277,19 +1298,78 @@ var LightPresetManagerEditor = class extends i4 {
setConfig(config) {
this._config = config;
}
_valueChanged(ev) {
const config = ev.detail.value;
if (this._config?.temperatures) {
config.temperatures = this._config.temperatures;
}
_dispatchConfig(newConfig) {
const event = new CustomEvent("config-changed", {
detail: { config },
detail: { config: newConfig },
bubbles: true,
composed: true
});
this.dispatchEvent(event);
this._config = config;
this._config = newConfig;
}
_mainValueChanged(ev) {
if (!this._config) return;
const newConfig = {
...this._config,
...ev.detail.value
};
this._dispatchConfig(newConfig);
}
// ---------------------------------------------------------------------------
// Lights management
// ---------------------------------------------------------------------------
_normalizeLight(light) {
if (typeof light === "string") {
return { entity: light };
}
return light;
}
_getLights() {
if (!this._config?.lights) return [];
return this._config.lights.map(this._normalizeLight);
}
_lightEntityChanged(index, ev) {
if (!this._config) return;
const value = ev.detail.value;
const lights = this._getLights();
if (value) {
lights[index] = { ...lights[index], entity: value };
}
this._dispatchConfig({ ...this._config, lights });
}
_lightNameChanged(index, ev) {
if (!this._config) return;
const target = ev.target;
const value = target.value || void 0;
const lights = this._getLights();
if (value) {
lights[index] = { ...lights[index], name: value };
} else {
delete lights[index].name;
}
this._dispatchConfig({ ...this._config, lights });
}
_addLight() {
if (!this._config) return;
const lights = this._getLights();
lights.push({ entity: "" });
this._dispatchConfig({ ...this._config, lights });
}
_removeLight(index) {
if (!this._config) return;
const lights = this._getLights();
lights.splice(index, 1);
const newConfig = { ...this._config };
if (lights.length > 0) {
newConfig.lights = lights;
} else {
delete newConfig.lights;
}
this._dispatchConfig(newConfig);
}
// ---------------------------------------------------------------------------
// Temperatures
// ---------------------------------------------------------------------------
_tempChanged(tempKey, ev) {
if (!this._config) return;
const target = ev.target;
@@ -1306,30 +1386,77 @@ var LightPresetManagerEditor = class extends i4 {
} else {
delete newConfig.temperatures;
}
const event = new CustomEvent("config-changed", {
detail: { config: newConfig },
bubbles: true,
composed: true
});
this.dispatchEvent(event);
this._config = newConfig;
this._dispatchConfig(newConfig);
}
// ---------------------------------------------------------------------------
// Render
// ---------------------------------------------------------------------------
render() {
if (!this.hass || !this._config) {
return b2``;
}
const lights = this._getLights();
const entitySelector = { entity: { domain: "light" } };
return b2`
<div class="form">
<!-- Main config -->
<ha-form
.hass=${this.hass}
.data=${this._config}
.schema=${SCHEMA}
.schema=${MAIN_SCHEMA}
.computeLabel=${this._computeLabel}
@value-changed=${this._valueChanged}
@value-changed=${this._mainValueChanged}
></ha-form>
<div class="temps-section">
<div class="temps-title">Color Temperatures (mireds)</div>
<!-- Individual Lights -->
<div class="section">
<div class="section-title">Individual Lights</div>
<div class="lights-list">
${lights.map(
(light, index) => b2`
<div class="light-item">
<div class="light-item-fields">
<div class="light-item-row">
<label>Entity</label>
<ha-selector-entity
.hass=${this.hass}
.selector=${entitySelector}
.value=${light.entity}
.required=${true}
@value-changed=${(ev) => this._lightEntityChanged(index, ev)}
></ha-selector-entity>
</div>
<div class="light-item-row">
<label>Name</label>
<input
type="text"
.value=${light.name || ""}
@input=${(ev) => this._lightNameChanged(index, ev)}
placeholder="Custom display name"
/>
</div>
</div>
<ha-icon
class="remove-btn"
icon="mdi:close"
@click=${() => this._removeLight(index)}
></ha-icon>
</div>
`
)}
<div class="add-btn" @click=${this._addLight}>
<ha-icon icon="mdi:plus"></ha-icon>
Add light
</div>
</div>
<span class="helper"
>Optional: individual lights for preset control</span
>
</div>
<!-- Temperatures -->
<div class="section">
<div class="section-title">Color Temperatures (mireds)</div>
<div class="temps-row">
<div class="temp-input">
<label>Warm</label>
@@ -1371,19 +1498,98 @@ LightPresetManagerEditor.styles = i`
gap: 16px;
}
.temps-section {
.section {
border: 1px solid var(--divider-color);
border-radius: 8px;
padding: 16px;
}
.temps-title {
.section-title {
font-weight: 500;
font-size: 14px;
color: var(--primary-text-color);
margin-bottom: 12px;
}
.lights-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.light-item {
display: flex;
gap: 8px;
align-items: flex-start;
padding: 8px;
background: var(--secondary-background-color);
border-radius: 8px;
}
.light-item-fields {
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
}
.light-item-row {
display: flex;
gap: 8px;
align-items: center;
}
.light-item-row ha-selector-entity {
flex: 1;
}
.light-item-row input {
flex: 1;
padding: 8px 12px;
border: 1px solid var(--divider-color);
border-radius: 4px;
font-size: 14px;
background: var(--primary-background-color);
color: var(--primary-text-color);
font-family: inherit;
}
.light-item-row input:focus {
outline: none;
border-color: var(--primary-color);
}
.light-item-row label {
font-size: 12px;
color: var(--secondary-text-color);
min-width: 50px;
}
.remove-btn {
color: var(--error-color);
cursor: pointer;
padding: 8px;
margin-top: 4px;
}
.remove-btn:hover {
opacity: 0.8;
}
.add-btn {
color: var(--primary-color);
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
font-size: 14px;
padding: 8px 0;
}
.add-btn:hover {
opacity: 0.8;
}
.temps-row {
display: flex;
gap: 8px;
@@ -1417,6 +1623,12 @@ LightPresetManagerEditor.styles = i`
outline: none;
border-color: var(--primary-color);
}
.helper {
font-size: 12px;
color: var(--secondary-text-color);
margin-top: 4px;
}
`;
__decorateClass([
n4({ attribute: false })
@@ -1428,7 +1640,7 @@ LightPresetManagerEditor = __decorateClass([
t3("light-preset-manager-editor")
], LightPresetManagerEditor);
console.log(
"%c LIGHT-PRESET-MANAGER-EDITOR %c v0.4.2 ",
"%c LIGHT-PRESET-MANAGER-EDITOR %c v0.5.0 ",
"background: #9b59b6; color: white; font-weight: bold; border-radius: 4px 0 0 4px;",
"background: #2ecc71; color: white; border-radius: 0 4px 4px 0;"
);
@@ -1474,10 +1686,13 @@ var LightPresetManager = class extends i4 {
get _supportsColorTemp() {
return supportsColorTemp(this._group);
}
get _currentTempZone() {
if (!this._config) return null;
return getCurrentTempZone(this._group, this._config.temperatures);
}
get _lights() {
if (!this.hass || !this._config) return [];
const lightIds = getLightsFromGroup(this._group, this._config.lights);
return lightIds.map((id) => this.hass.states[id]).filter((e5) => e5 !== void 0);
return getLightsFromGroup(this._group, this._config.lights);
}
// ---------------------------------------------------------------------------
// Actions - Global
@@ -1537,11 +1752,9 @@ var LightPresetManager = class extends i4 {
// ---------------------------------------------------------------------------
render() {
if (!this.hass || !this._config || !this._t) {
return b2`<ha-card
><div class="card-content">
${this._t?.card.loading || "Loading..."}
</div></ha-card
>`;
return b2`<ha-card>
<div class="card-content">${this._t?.card.loading || "Loading..."}</div>
</ha-card>`;
}
return b2`
<ha-card .header=${this._config.title || ""}>
@@ -1585,12 +1798,13 @@ var LightPresetManager = class extends i4 {
}
_renderGlobalTemperature() {
const isOn = this._isOn;
const currentZone = this._currentTempZone;
const t4 = this._t;
return b2`
<div class="temp-section">
<div class="temp-buttons">
<button
class="temp-button warm"
class="temp-button warm ${currentZone === "warm" ? "active" : ""}"
@click=${() => this._setTemperature("warm")}
?disabled=${!isOn}
>
@@ -1598,7 +1812,7 @@ var LightPresetManager = class extends i4 {
${t4.temperature.warm}
</button>
<button
class="temp-button neutral"
class="temp-button neutral ${currentZone === "neutral" ? "active" : ""}"
@click=${() => this._setTemperature("neutral")}
?disabled=${!isOn}
>
@@ -1606,7 +1820,7 @@ var LightPresetManager = class extends i4 {
${t4.temperature.neutral}
</button>
<button
class="temp-button cold"
class="temp-button cold ${currentZone === "cold" ? "active" : ""}"
@click=${() => this._setTemperature("cold")}
?disabled=${!isOn}
>
@@ -1626,22 +1840,26 @@ var LightPresetManager = class extends i4 {
>
</div>
<div class="lights-list">
${this._lights.map((entity) => this._renderLightRow(entity))}
${this._lights.map(
(lightConfig) => this._renderLightRow(lightConfig)
)}
</div>
</div>
`;
}
_renderLightRow(entity) {
_renderLightRow(lightConfig) {
const entity = this.hass?.states[lightConfig.entity];
const isOn = isEntityOn(entity);
const available = isEntityAvailable(entity);
const brightness = getBrightnessPercent(entity);
const name = getEntityName(entity);
const name = getEntityName(entity, lightConfig.name);
const hasColorTemp = supportsColorTemp(entity);
const currentZone = this._config ? getCurrentTempZone(entity, this._config.temperatures) : null;
return b2`
<div class="light-row">
<button
class="light-toggle ${isOn ? "on" : ""}"
@click=${() => this._toggleLight(entity.entity_id)}
@click=${() => this._toggleLight(lightConfig.entity)}
?disabled=${!available}
>
<ha-icon icon="mdi:lightbulb${isOn ? "" : "-outline"}"></ha-icon>
@@ -1658,31 +1876,31 @@ var LightPresetManager = class extends i4 {
min="1"
max="100"
.value=${String(isOn ? brightness : 0)}
@change=${(e5) => this._setLightBrightness(entity.entity_id, e5)}
@change=${(e5) => this._setLightBrightness(lightConfig.entity, e5)}
?disabled=${!isOn || !available}
/>
${hasColorTemp ? b2`
<div class="light-temp-buttons">
<button
class="light-temp-button warm"
@click=${() => this._setLightTemperature(entity.entity_id, "warm")}
class="light-temp-button warm ${currentZone === "warm" ? "active" : ""}"
@click=${() => this._setLightTemperature(lightConfig.entity, "warm")}
?disabled=${!isOn || !available}
title="${this._t.temperature.warm}"
>
<ha-icon icon="mdi:weather-sunny"></ha-icon>
</button>
<button
class="light-temp-button neutral"
@click=${() => this._setLightTemperature(entity.entity_id, "neutral")}
class="light-temp-button neutral ${currentZone === "neutral" ? "active" : ""}"
@click=${() => this._setLightTemperature(lightConfig.entity, "neutral")}
?disabled=${!isOn || !available}
title="${this._t.temperature.neutral}"
>
<ha-icon icon="mdi:circle-half-full"></ha-icon>
</button>
<button
class="light-temp-button cold"
@click=${() => this._setLightTemperature(entity.entity_id, "cold")}
class="light-temp-button cold ${currentZone === "cold" ? "active" : ""}"
@click=${() => this._setLightTemperature(lightConfig.entity, "cold")}
?disabled=${!isOn || !available}
title="${this._t.temperature.cold}"
>
@@ -1712,9 +1930,15 @@ LightPresetManager = __decorateClass([
t3("light-preset-manager")
], LightPresetManager);
window.customCards = window.customCards || [];
window.cu;
window.customCards.push({
type: "light-preset-manager",
name: "Light Preset Manager",
description: "Light control panel with saveable presets",
preview: true,
documentationURL: "https://github.com/your-repo/light-preset-manager"
});
console.log(
"%c LIGHT-PRESET-MANAGER %c v0.4.1 ",
"%c LIGHT-PRESET-MANAGER %c v0.5.3 ",
"background: #3498db; color: white; font-weight: bold; border-radius: 4px 0 0 4px;",
"background: #2ecc71; color: white; border-radius: 0 4px 4px 0;"
);