diff --git a/dist/hpsu-dashboard-card-editor.js b/dist/hpsu-dashboard-card-editor.js index 0d85f5a..634dd14 100644 --- a/dist/hpsu-dashboard-card-editor.js +++ b/dist/hpsu-dashboard-card-editor.js @@ -25,7 +25,7 @@ class HpsuDashboardCardEditor extends LitElement { this.entities_configuration = await this.loadModule(); this.entities_configuration = this.entities_configuration.map( (entity) => { - entity.entityId = config.entities[entity.confEntityId] || "default"; + entity.entityId = config.entities[entity.id]; return entity; } ); @@ -42,20 +42,20 @@ class HpsuDashboardCardEditor extends LitElement { ${this.entities_configuration.map( (entity) => { return html` -
${(entity.category) ? html`

${entity.category}

` : ""} -
`; + >`; } )} `; @@ -64,17 +64,9 @@ class HpsuDashboardCardEditor extends LitElement { _entityChanged(event) { event.stopPropagation(); - //const curValue = (event.currentTarget as any).curValue; - const curValue = event.currentTarget.curValue; - const newValue = event.detail.value; - - const entity_conf = this.entities_configuration.find((entity) => entity.label == event.target.label); - if (entity_conf) { - this.config.entities[entity_conf.confEntityId] = newValue; - this.dispatchEvent(new CustomEvent('config-changed', { detail: { config: this.config } })); - } else { - console.error(`Entity configuration with label <${event.target.label}> not found!`); - } + const entityId = event.target.getAttribute("data-id"); + this.config.entities[entityId] = event.detail.value; + this.dispatchEvent(new CustomEvent('config-changed', { detail: { config: this.config } })); } static get styles() { diff --git a/dist/hpsu-dashboard-card.js b/dist/hpsu-dashboard-card.js index dd80533..2d67860 100644 --- a/dist/hpsu-dashboard-card.js +++ b/dist/hpsu-dashboard-card.js @@ -1,38 +1,24 @@ class HPSUDashboardCard extends HTMLElement { - setConfig(config) { + inititialized = false; + + async setConfig(config) { + //console.log(">> setConfig"); if (!config.entities) { throw new Error("Required entities field is missing"); } - this.entities_configuration = [ - { confEntityId: "t_aussen_1", rectId: "T-Aussen-1-Value", offset: 6 }, - { confEntityId: "t_aussen_2", rectId: "T-Aussen-2-Value", offset: 6 }, - { confEntityId: "expansions_ventil", rectId: "EEV-Value", offset: 6 }, - { confEntityId: "kondensat", rectId: "Kondensat-Value", offset: 6 }, - { confEntityId: "umwaelzpumpe", rectId: "Umwaelzpumpe-Value", offset: 6 }, - { confEntityId: "umwaelzpumpe_an_aus", rectId: "circulation_pump_on_off_rect", fontSize: "30px", offset: 2 }, - { confEntityId: "durchfluss", rectId: "Durchfluss-Value", offset: 6 }, - { confEntityId: "ruecklauf_1", rectId: "Ruecklauf-1-Value", offset: 6 }, - { confEntityId: "ruecklauf_2", rectId: "Ruecklauf-2-Value", offset: 6 }, - { confEntityId: "verdampfer", rectId: "Verdampfer-Value", offset: 6 }, - { confEntityId: "vorlauf_1", rectId: "Vorlauf-1-Value", offset: 6 }, - { confEntityId: "vorlauf_2", rectId: "Vorlauf-2-Value", offset: 6 }, - { confEntityId: "vorlauf_soll", rectId: "Vorlauf-Soll-Value", offset: 6 }, - { confEntityId: "wasserdruck", rectId: "Druck-Value", offset: 6 }, - { confEntityId: "vorlauf_bh_1", rectId: "Vorlauf-BH-1-Value", offset: 6 }, - { confEntityId: "vorlauf_bh_2", rectId: "Vorlauf-BH-2-Value", offset: 6 }, - { confEntityId: "kompressor_an_aus", rectId: "compressor_on_off_rect", fontSize: "40px", offset: 2 }, - { confEntityId: "luefter", rectId: "Luefter-Value", offset: 6 }, - { confEntityId: "verdichter", rectId: "Verdichter-Value", offset: 6 }, - { confEntityId: "speicher", rectId: "Speicher-Value", offset: 6 }, - { confEntityId: "speicher_soll", rectId: "Speicher-Soll-Value", offset: 6 }, - { confEntityId: "mischer", rectId: "DHW-Mixer-Value", fontSize: "40px", offset: 6 }, - { confEntityId: "bypass", rectId: "Bypass-Value", fontSize: "40px", offset: 6 } - ]; + this.entities_configuration = await this.loadModule(); + this.entities_configuration = this.entities_configuration.map( + (entity) => { + entity.entityId = config.entities[entity.id]; + return entity; + } + ); this.config = config; this.attachShadow({ mode: "open" }); this.render(); + //console.log("<< setConfig"); } static getConfigElement() { @@ -41,6 +27,7 @@ class HPSUDashboardCard extends HTMLElement { } async render() { + //console.log(">> render"); const scriptUrl = import.meta.url; const urlParams = new URLSearchParams(scriptUrl.split('?')[1]); @@ -78,10 +65,17 @@ class HPSUDashboardCard extends HTMLElement { this.shadowRoot.appendChild(svgElement); this.createCSS(); + + this.inititialized = true; + + this.updateLabels(); this.updateOpacity(); + + //console.log("<< render"); } createCSS() { + //console.log(">> createCSS"); const style = document.createElement('style'); style.textContent = ` svg { @@ -105,9 +99,7 @@ class HPSUDashboardCard extends HTMLElement { } `; this.shadowRoot.appendChild(style); - } - connectedCallback() { const ha = document.querySelector("home-assistant"); if (ha) { const homeAssistantStyle = document.createElement("style"); // Removes additional empty scroll area on smmobile phones @@ -129,133 +121,155 @@ class HPSUDashboardCard extends HTMLElement { const huiPanelViewShadowRoot = huiCard.getRootNode(); huiPanelViewShadowRoot.appendChild(huiPanelViewStyle); } + //console.log("<< createCSS"); } - updateOpacity() { - const flowArrows = this.shadowRoot.querySelector(`#DHW-Flow-Arrows`); - const flowReturnArrows = this.shadowRoot.querySelector(`#DHW-Flow-Return-Arrows`); - const heatingArrows = this.shadowRoot.querySelector(`#Heating-Flow-Arrows`); - - if (!flowArrows || !flowReturnArrows || !heatingArrows) return; + connectedCallback() { + } - const flow_rate_id = this.config.entities['durchfluss']; - const mixer_id = this.config.entities['mischer']; - const bypass_id = this.config.entities['bypass']; + set hass(hass) { + //console.log(">> hass"); - const flowRate = flow_rate_id ? parseFloat(this._hass.states[flow_rate_id].state) : 0; - const mischerState = mixer_id ? parseFloat(this._hass.states[mixer_id].state) : 0; - const bpvState = bypass_id ? parseFloat(this._hass.states[bypass_id].state) : 0; + this._hass = hass; - flowArrows.style.opacity = flowRate > 0 ? (mischerState / 100.0) : 0; - flowReturnArrows.style.opacity = flowRate > 0 ? (bpvState / 100.0) : 0; - heatingArrows.style.opacity = flowRate > 0 ? ((100 - bpvState) / 100.0) : 0; + this.updateLabels(); + this.updateOpacity(); - for (let index = 1; index <= 8; ++index) { - const arrow = this.shadowRoot.querySelector(`#Flow-Arrow-${index}`); - arrow.style.opacity = (flowRate > 0) * 1; - } - } - - set hass(hass) { - this._hass = hass; - this.updateLabels(); - this.updateOpacity(); + //console.log("<< hass"); } get hass() { - return this._hass; + return this._hass; } createStateLabels(svgDoc) { + //console.log(">> createStateLabels"); this.entities_configuration.forEach(state => { const valueBox = svgDoc.getElementById(state.rectId); if (valueBox) { const group = valueBox.parentNode; - if (group && valueBox) { + if (group) { const transform = valueBox.getAttribute('transform'); - const fontSize = state.fontSize || "60px"; - state.entityId = this.config.entities[state.confEntityId]; + state.entityId = this.config.entities[state.id]; + const labelElement = document.createElementNS("http://www.w3.org/2000/svg", "text"); if (state.entityId) { - const label = document.createElementNS("http://www.w3.org/2000/svg", "text"); - label.id = state.entityId.replace(".", "_"); - label.setAttribute("text-anchor", "middle"); - label.setAttribute("dominant-baseline", "middle"); - label.setAttribute("cursor", "pointer"); - label.setAttribute("fill", "blue"); - label.setAttribute("font-size", fontSize); - label.setAttribute("stroke-width", "1"); - if (transform) { - label.setAttribute("transform", transform); - } - - state.label = label; - state.valueBox = valueBox; + labelElement.id = state.entityId.replace(".", "_"); + } - if (this._hass.states[state.entityId] !== undefined) { - label.textContent = this._hass.states[state.entityId].state; + labelElement.setAttribute("cursor", "pointer"); + labelElement.setAttribute("dominant-baseline", "middle"); + labelElement.setAttribute("stroke-width", "1"); + labelElement.addEventListener("click", () => { + this.handleStateClick(state.entityId); + }); - label.addEventListener("click", () => { - this.handleStateClick(state.entityId); - }); - } else { - console.warn(`Entity with ID ${state.entityId} not found`); - } - group.appendChild(label); + if (transform) { + labelElement.setAttribute("transform", transform); } + + state.labelElement = labelElement; + state.valueBox = valueBox; + group.appendChild(labelElement); } else { - console.warn(`Rect with ID ${state.rectId} not found.`); + console.warn(`Rect with ID ${state.rectId} parent not found.`); } } else { console.warn(`Rect with ID ${state.rectId} not found.`); } }); - - this.updateLabels(); } updateLabels() { - if (this.entities_configuration) { - this.entities_configuration.forEach(state => { - if (state.entityId) { - const newState = this._hass.states[state.entityId]; + //console.log(">> updateLabels: " + this.config + ":" + this.inititialized); + if (this.config && this.inititialized) { + if (this.entities_configuration) { + this.entities_configuration.forEach(state => { + const newState = state.entityId ? this._hass.states[state.entityId] : null; if (state.valueBox) { - if (state.label) { + if (state.labelElement) { const xPos = parseFloat(state.valueBox.getAttribute('x')); const yPos = parseFloat(state.valueBox.getAttribute('y')); const width = parseFloat(state.valueBox.getAttribute('width')); const height = parseFloat(state.valueBox.getAttribute('height')); - const fontSize = parseFloat(state.label.getAttribute("font-size")) || 46; + const fontSize = state.fontSize || 56; - if (newState) { - const entityState = newState.state || "--"; + if (!newState) { + state.labelElement.textContent = "N/D"; + state.labelElement.setAttribute("fill", "orange"); + state.labelElement.setAttribute("font-size", "30px"); + } else if (newState.state == "unknown" || newState.state == "unavailable") { + state.labelElement.textContent = "N/A"; + state.labelElement.setAttribute("fill", "orange"); + state.labelElement.setAttribute("font-size", "30px"); + } else { + let entityState = newState.state || "--"; const unit = newState.attributes.unit_of_measurement || ""; + state.labelElement.setAttribute("font-size", fontSize); if (this.isBooleanSensor(state.entityId)) { - state.label.textContent = entityState === "on" ? "An" : "Aus"; - state.label.setAttribute("fill", entityState === "on" ? "yellow" : "white"); + state.labelElement.textContent = entityState === "on" ? "An" : "Aus"; + state.labelElement.setAttribute("fill", entityState === "on" ? "yellow" : "white"); } else { - state.label.textContent = `${this.formatNumber(entityState)} ${unit}`; - state.label.setAttribute("fill", "silver"); + entityState = this.formatNumber(entityState); + if (entityState == "Warmwasserbereitung") { + entityState = "Warmwasser"; + } + if (state.suffix) { + entityState = state.suffix + entityState; + } + + state.labelElement.textContent = `${entityState} ${unit}`; + state.labelElement.setAttribute("fill", "silver"); } - } else { - state.label.textContent = "INVALID"; - state.label.setAttribute("fill", "orange"); - state.label.setAttribute("font-size", "30px"); } - state.label.setAttribute("x", xPos + width / 2); - state.label.setAttribute("y", yPos + height / 2 + state.offset); + if (state.align == "left") { + state.labelElement.setAttribute("x", xPos); + state.labelElement.setAttribute("text-anchor", "start"); + } else { + state.labelElement.setAttribute("x", xPos + width / 2); + state.labelElement.setAttribute("text-anchor", "middle"); + } + state.labelElement.setAttribute("y", yPos + height / 2 + state.offset); } else { console.warn("Label not found: " + state.entityId); } } else { console.warn("ValueBox not found: " + state.entityId); } - } - }); + }); + } + } + //console.log("<< updateLabels"); + } + + updateOpacity() { + if (this.config && this.inititialized) { + const flowArrows = this.shadowRoot.querySelector(`#DHW-Flow-Arrows`); + const flowReturnArrows = this.shadowRoot.querySelector(`#DHW-Flow-Return-Arrows`); + const heatingArrows = this.shadowRoot.querySelector(`#Heating-Flow-Arrows`); + + if (!flowArrows || !flowReturnArrows || !heatingArrows) return; + + const flow_rate_id = this.config.entities['durchfluss']; + const mixer_id = this.config.entities['mischer']; + const bypass_id = this.config.entities['bypass']; + + const flowRate = flow_rate_id ? parseFloat(this._hass.states[flow_rate_id].state) : 0; + const mischerState = mixer_id ? parseFloat(this._hass.states[mixer_id].state) : 0; + const bpvState = bypass_id ? parseFloat(this._hass.states[bypass_id].state) : 0; + + flowArrows.style.opacity = flowRate > 0 ? (mischerState / 100.0) : 0; + flowReturnArrows.style.opacity = flowRate > 0 ? (bpvState / 100.0) : 0; + heatingArrows.style.opacity = flowRate > 0 ? ((100 - bpvState) / 100.0) : 0; + + for (let index = 1; index <= 8; ++index) { + const arrow = this.shadowRoot.querySelector(`#Flow-Arrow-${index}`); + arrow.style.opacity = (flowRate > 0) * 1; + } } } @@ -291,6 +305,15 @@ class HPSUDashboardCard extends HTMLElement { isNumeric(value) { return /^-?\d+$/.test(value); } + + async loadModule() { + try { + const module = await import('/local/daikin-rotex-hpsu-dashboard/modules.js'); + return module.entities_configuration; + } catch (error) { + console.error("Modul konnte nicht geladen werden:", error); + } + } } customElements.define("hpsu-dashboard-card", HPSUDashboardCard); \ No newline at end of file diff --git a/dist/hpsu.svg b/dist/hpsu.svg index b58e054..fbd0f87 100644 --- a/dist/hpsu.svg +++ b/dist/hpsu.svg @@ -21,15 +21,15 @@ inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" - inkscape:zoom="0.45254834" - inkscape:cx="258.53592" - inkscape:cy="222.07572" + inkscape:zoom="0.90509668" + inkscape:cx="2186.5067" + inkscape:cy="1138.5524" inkscape:window-width="1920" inkscape:window-height="1129" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:window-maximized="1" - inkscape:current-layer="Kondensat" + inkscape:current-layer="layer1" showgrid="false" />LüfterVorlauf BHVorlauf BHT-Außen 2T-Außen T-Außen 1 + id="text26" + x="113.77716" + y="136">Außentemp diff --git a/dist/modules.js b/dist/modules.js index f2fecfc..ab888cd 100644 --- a/dist/modules.js +++ b/dist/modules.js @@ -1,27 +1,30 @@ export const entities_configuration = [ - { confEntityId: "t_aussen_1", label: "Außentemperatur", type: "sensor", rectId: "T-Aussen-1-Value", offset: 6, category: "Reihe 1", unit: "°C" }, - { confEntityId: "t_aussen_2", label: "T-Außen", type: "sensor", rectId: "T-Aussen-2-Value", offset: 6, unit: "°C" }, - { confEntityId: "expansions_ventil", label: "EEV", type: "sensor", rectId: "EEV-Value", offset: 6, unit: "%" }, - { confEntityId: "kondensat", label: "Kondensat", type: "sensor", rectId: "Kondensat-Value", offset: 6, unit: "°C" }, - { confEntityId: "umwaelzpumpe", label: "Umwälzpumpe", type: "sensor", rectId: "Umwaelzpumpe-Value", offset: 6, unit: "%" }, - { confEntityId: "umwaelzpumpe_an_aus", label: "Außentemperatur", type: "binary_sensor", rectId: "circulation_pump_on_off_rect", fontSize: "30px", offset: 2 }, - { confEntityId: "durchfluss", label: "Durchfluss", type: "sensor", rectId: "Durchfluss-Value", offset: 6 }, - { confEntityId: "ruecklauf_1", label: "Rücklauf 1", type: "sensor", rectId: "Ruecklauf-1-Value", offset: 6, unit: "°C" }, - { confEntityId: "ruecklauf_2", label: "Rücklauf 2", type: "sensor", rectId: "Ruecklauf-2-Value", offset: 6, unit: "°C" }, - { confEntityId: "verdampfer", label: "Verdampfer", type: "sensor", rectId: "Verdampfer-Value", offset: 6, category: "Reihe 2", unit: "°C" }, - { confEntityId: "vorlauf_1", label: "Vorlauf 1", type: "sensor", rectId: "Vorlauf-1-Value", offset: 6, unit: "°C" }, - { confEntityId: "vorlauf_2", label: "Vorlauf 2", type: "sensor", rectId: "Vorlauf-2-Value", offset: 6, unit: "°C" }, - { confEntityId: "vorlauf_soll", label: "VorlaufSoll", type: "sensor", rectId: "Vorlauf-Soll-Value", offset: 6, unit: "°C" }, - { confEntityId: "wasserdruck", label: "Wasserdruck", type: "sensor", rectId: "Druck-Value", offset: 6 }, - { confEntityId: "vorlauf_bh_1", label: "VorlaufBH 1", type: "sensor", rectId: "Vorlauf-BH-1-Value", offset: 6, unit: "°C" }, - { confEntityId: "vorlauf_bh_2", label: "VorlaufBH 2", type: "sensor", rectId: "Vorlauf-BH-2-Value", offset: 6, unit: "°C" }, - { confEntityId: "kompressor_an_aus", label: "Kompressor AN/AUS", type: "binary_sensor", rectId: "compressor_on_off_rect", fontSize: "40px", offset: 2 }, - { confEntityId: "luefter", label: "Lüfter", type: "sensor", rectId: "Luefter-Value", offset: 6, category: "Reihe 3", unit: "RPM" }, - { confEntityId: "verdichter", label: "Verdichter", type: "sensor", rectId: "Verdichter-Value", offset: 6, unit: "RPM" }, - { confEntityId: "speicher", label: "Speicher", type: "sensor", rectId: "Speicher-Value", offset: 6, unit: "°C" }, - { confEntityId: "speicher_soll", label: "SpeicherSoll", type: "select", rectId: "Speicher-Soll-Value", offset: 6, unit: "°C" }, - { confEntityId: "mischer", label: "Mischer", type: "sensor", rectId: "DHW-Mixer-Value", fontSize: "40px", offset: 6, unit: "%" }, - { confEntityId: "bypass", label: "Beipass", type: "sensor", rectId: "Bypass-Value", fontSize: "40px", offset: 6, unit: "%" } + { id: "t_aussen_1", label: "Außentemperatur", type: "sensor", rectId: "aussentemp_val", offset: 6, category: "Reihe 1", unit: "°C" }, + { id: "t_aussen_2", label: "T-Außen", type: "sensor", rectId: "taussen_val", offset: 6, unit: "°C" }, + { id: "expansions_ventil", label: "Elektonisches Expansionsventil", type: "sensor", rectId: "eev_val", offset: 6, unit: "%" }, + { id: "kondensat", label: "Kondensat", type: "sensor", rectId: "Kondensat-Value", offset: 6, unit: "°C" }, + { id: "umwaelzpumpe", label: "Umwälzpumpe", type: "sensor", rectId: "Umwaelzpumpe-Value", offset: 6, unit: "%" }, + { id: "umwaelzpumpe_an_aus", label: "Status Umwälzpumpe", type: "binary_sensor", rectId: "circ_pump_rect", offset: 2, fontSize: "30px" }, + { id: "durchfluss", label: "Durchfluss", type: "sensor", rectId: "Durchfluss-Value", offset: 6 }, + { id: "ruecklauf_1", label: "Rücklauf CAN", type: "sensor", rectId: "Ruecklauf-1-Value", offset: 6, unit: "°C" }, + { id: "ruecklauf_2", label: "Rücklauf UART", type: "sensor", rectId: "Ruecklauf-2-Value", offset: 6, unit: "°C" }, + { id: "verdampfer", label: "Verdampfer", type: "sensor", rectId: "Verdampfer-Value", offset: 6, category: "Reihe 2", unit: "°C" }, + { id: "vorlauf_1", label: "Vorlauf CAN", type: "sensor", rectId: "Vorlauf-1-Value", offset: 6, unit: "°C" }, + { id: "vorlauf_2", label: "Vorlauf UART", type: "sensor", rectId: "Vorlauf-2-Value", offset: 6, unit: "°C" }, + { id: "vorlauf_soll", label: "Vorlauf Soll", type: "sensor", rectId: "Vorlauf-Soll-Value", offset: 6, unit: "°C" }, + { id: "wasserdruck", label: "Wasserdruck", type: "sensor", rectId: "Druck-Value", offset: 6 }, + { id: "vorlauf_bh_1", label: "VorlaufBH CAN", type: "sensor", rectId: "Vorlauf-BH-1-Value", offset: 6, unit: "°C" }, + { id: "vorlauf_bh_2", label: "VorlaufBH UART", type: "sensor", rectId: "Vorlauf-BH-2-Value", offset: 6, unit: "°C" }, + { id: "kompressor_an_aus", label: "Status Kompressor", type: "binary_sensor", rectId: "comp_rect", offset: 2, fontSize: "40px" }, + { id: "luefter", label: "Lüfter", type: "sensor", rectId: "Luefter-Value", offset: 6, category: "Reihe 3", unit: "RPM" }, + { id: "verdichter", label: "Verdichter", type: "sensor", rectId: "Verdichter-Value", offset: 6, unit: "RPM" }, + { id: "speicher", label: "Speicher Ist", type: "sensor", rectId: "Speicher-Value", offset: 6, unit: "°C" }, + { id: "speicher_soll", label: "Speicher Soll", type: "select", rectId: "Speicher-Soll-Value", offset: 6, unit: "°C" }, + { id: "mischer", label: "Mischer", type: "sensor", rectId: "DHW-Mixer-Value", offset: 6, unit: "%", fontSize: "40px" }, + { id: "bypass", label: "Bypass", type: "sensor", rectId: "Bypass-Value", offset: 6, unit: "%", fontSize: "40px" }, + { id: "betriebsmodus", label: "Betriebsmodus", type: "select", rectId: "info_1", offset: 6, fontSize: "40px", align: "left", "suffix": "Modus: " }, + { id: "betriebsart", label: "Betriebsart", type: "text_sensor", rectId: "info_2", offset: 6, fontSize: "40px", align: "left", "suffix": "Betriebsart: " }, + { id: "thermische_leistung", label: "Thermische Leistung", type: "sensor", rectId: "info_3", offset: 6, fontSize: "40px", align: "left", "suffix": "Therm. Leistung: " } ]; function getConfig() {