├── linky.png ├── content-card-linky.png ├── hacs.json ├── content-card-linky-editor.png ├── .github └── workflows │ └── main.yml ├── LICENSE ├── README.md └── dist ├── content-card-linky-editor.js └── content-card-linky.js /linky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saniho/content-card-linky/HEAD/linky.png -------------------------------------------------------------------------------- /content-card-linky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saniho/content-card-linky/HEAD/content-card-linky.png -------------------------------------------------------------------------------- /hacs.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Linky Content Card", 3 | "country": "FR", 4 | "render_readme": true 5 | } 6 | -------------------------------------------------------------------------------- /content-card-linky-editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saniho/content-card-linky/HEAD/content-card-linky-editor.png -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Validate for HACS 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: '0 0 * * *' 8 | 9 | jobs: 10 | hacs: 11 | name: HACS Action 12 | runs-on: "ubuntu-latest" 13 | steps: 14 | - uses: "actions/checkout@v2" 15 | - name: HACS Action 16 | uses: "hacs/action@main" 17 | with: 18 | category: "plugin" 19 | ignore: "brands" 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Project based on https://github.com/saniho/content-card-linky. 2 | 3 | MIT License 4 | 5 | Copyright (c) 2021 Nicolas Bourasseau 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pré-avis: cette carte est en train d'être abandonné en faveur de son successor (copie) dans le domain de MyElectricalData 2 | Pour en profiter, il faut désinstaller cette carte et reïnstaller https://github.com/MyElectricalData/content-card-linky 3 | 4 | - 5 | - 6 | - 7 | - 8 | - 9 | - 10 | 11 | 12 | 13 | ## content-card-linky 14 | [![HACS Supported](https://img.shields.io/badge/HACS-Supported-green.svg)](https://github.com/custom-components/hacs) 15 | 16 | **Cette carte est compatible avec l'integration : [MyElectricalData](https://github.com/MyElectricalData/myelectricaldata)** 17 | 18 | Depuis Aout 2023: avec le changement vers MyElectricalData, cette carte **n'est plus garanti d'être compatible** avec l'integration : [MyEnedis](https://github.com/saniho/apiEnedis) 19 | 20 | **Un question ? Un problème ? Une demande ? Venez en parler sur le [forum HACF](https://forum.hacf.fr/).** 21 | 22 | ## Bienvenue ! 23 | 24 | Cette carte est initialement inspirée de [@royto](https://github.com/royto/linky-card) 25 | 26 | Avant de pouvoir utiliser cette intégration, assurez vous : 27 | * D'avoir validé l'installation correcte de [MyElectricalData](https://github.com/MyElectricalData/myelectricaldata) 28 | 29 | ## Installer la carte 30 |
31 | Via HACS (mise à jour en un clic) :
32 | 33 | * Ouvrez HACS, cliquez sur `Frontend`, puis selectionnez le menu 3 points en haut à droite. 34 | 35 | *si vous n'avez pas HACS, pour l'installer cela se passe ici : [HACS : Ajoutez des modules et des cartes personnalisées](https://forum.hacf.fr/t/hacs-ajoutez-des-modules-et-des-cartes-personnalisees/359) 36 | 37 | * Ajoutez le dépot personnalisé : `https://github.com/saniho/content-card-linky` 38 | 39 | * Choisir la catégorie `Lovelace` 40 | 41 | * Cliquez sur le bouton `Installer` de la carte 42 | 43 | * Cliquez sur le bouton `Installer` de la popup 44 | 45 | * La carte est maintenant rouge, signifiant qu'un redémarrage du serveur Home Assistant est nécessaire 46 | 47 | * Accédez à la vue `Contrôle du serveur` (`Configuration` -> `Contrôle du serveur`), puis cliquez sur le bouton `Redémarrer` dans la zone `Gestion du serveur` 48 |
49 | 50 |
51 | Manuellement (à faire à chaque mise à jour) 52 | * Telecharger le fichier [content-card-linky.js](https://github.com/saniho/content-card-linky/blob/main/content-card-linky.js) et le dossier [images](https://github.com/saniho/content-card-linky/tree/main/images) 53 | 54 | * Les mettre dans votre repertoire `www` et l'ajouter dans l'interface ressource 55 | 56 | * Configurez la ressource dans votre fichier de configuration. 57 | 58 | ``` 59 | resources: 60 | - url: /hacsfiles/content-card-linky/content-card-linky.js 61 | type: module 62 | ``` 63 |
64 | 65 | ## Ajouter la carte 66 |
67 | Via l'interface graphique 68 | * Ajoutez une carte via l'interface graphique, et configurez les options comme vous le désirez. 69 | 70 |
71 |
72 | En YAML 73 | * Dans votre éditeur lovelace, ajouter ceci : 74 | 75 | ```` 76 | type: 'custom:content-card-linky' 77 | entity: sensor.xxx_myelctricaldata_xxxx 78 | ```` 79 |
80 | 81 | ### Redémarrer votre serveur Home Assistant 82 | 83 | ## Options disponibles 84 | 85 | ```` 86 | type: custom:content-card-linky Type de la carte 87 | nbJoursAffichage: '7' Nombre de jour historique 88 | titleName: Consommation d'hier Titre 89 | entity: sensor.myelectricaldata_123456 Sensor de l'integration MyElectricalData 90 | ewEntity: sensor.myelectricaldata_123456_J0 Sensor de l'intégration Ecowatt J+0 via (!) MyElectricalData (sensor dispo dès MyElectricaldata v0.9.1) 91 | ewEntityJ1: sensor.myelectricaldata_123456_J1 Sensor de l'intégration Ecowatt J+1 via (!) MyElectricalData (sensor dispo dès MyElectricaldata v0.9.1) 92 | ewEntityJ2: sensor.myelectricaldata_123456_J2 Sensor de l'intégration Ecowatt J+2 via (!) MyElectricalData (sensor dispo dès MyElectricaldata v0.9.1) 93 | tempoInfo: sensor.myelec..._tempoinfo Sensor de l'intégratoin Tempo, contient des prix et jours restant par couleur (sensor dispo dès v0.9.2 ou en dev 0.9.2.b4) 94 | tempoEntityJ0: sensor.myelec..._tempotoday Sensor de l'intégration Tempo aujourd'hui 95 | tempoEntityJ1: sensor.myelec..._tempotomorrow Sensor de l'intégration Tempo demain 96 | showIcon: false Affiche l'icon Linky 97 | showHistory: true Affiche l'historique sur plusieurs jours 98 | showInTableUnit: false 99 | showDayPriceHCHP: false 100 | showDayHCHP: false 101 | showMonthRatio: false 102 | showTitle: true 103 | showPeakOffPeak: false 104 | showDayPrice: true 105 | showPrice: true Affiche le prix de l'historique 106 | showCurrentMonthRatio: true 107 | showWeekRatio: true 108 | showDayName: short Affichage des jours de la semaine : "short", "narrow", "long" 109 | showDayMaxPower: true Affichage MaxPower avec indication si dépassé 110 | showTitreLigne: true 111 | showEcoWatt: true Affichage EcoWatt pour ajourd'hui 112 | showEcoWattJ12: false Affichage EcoWatt pour demains et après (sensor dispo dès MyElectricaldata v0.9.1) 113 | showTempo: false Affichage Tempo 114 | ```` 115 | 116 | ![image](https://github.com/saniho/content-card-linky/assets/44190435/222621d5-70bb-4b69-97a7-6d140f6de98e) 117 | 118 | 119 | 120 | ************** 121 | 122 | N'hésitez pas à aller faire un tour sur ce forum ou vous trouverez pleins d'informations 123 | 124 | https://forum.hacf.fr/t/hacs-ajoutez-des-modules-et-des-cartes-personnalisees/359 125 | 126 | ************* 127 | -------------------------------------------------------------------------------- /dist/content-card-linky-editor.js: -------------------------------------------------------------------------------- 1 | const fireEvent = (node, type, detail, options) => { 2 | options = options || {}; 3 | detail = detail === null || detail === undefined ? {} : detail; 4 | const event = new Event(type, { 5 | bubbles: options.bubbles === undefined ? true : options.bubbles, 6 | cancelable: Boolean(options.cancelable), 7 | composed: options.composed === undefined ? true : options.composed, 8 | }); 9 | event.detail = detail; 10 | node.dispatchEvent(event); 11 | return event; 12 | }; 13 | 14 | if ( 15 | !customElements.get("ha-switch") && 16 | customElements.get("paper-toggle-button") 17 | ) { 18 | customElements.define("ha-switch", customElements.get("paper-toggle-button")); 19 | } 20 | 21 | if (!customElements.get("ha-entity-picker")) { 22 | (customElements.get("hui-entities-card")).getConfigElement(); 23 | } 24 | 25 | const LitElement = customElements.get("hui-masonry-view") ? Object.getPrototypeOf(customElements.get("hui-masonry-view")) : Object.getPrototypeOf(customElements.get("hui-view")); 26 | const html = LitElement.prototype.html; 27 | const css = LitElement.prototype.css; 28 | 29 | const HELPERS = window.loadCardHelpers(); 30 | 31 | export class contentCardLinkyEditor extends LitElement { 32 | setConfig(config) { 33 | this._config = { ...config }; 34 | } 35 | 36 | static get properties() { 37 | return { hass: {}, _config: {} }; 38 | } 39 | 40 | get _entity() { 41 | return this._config.entity || ""; 42 | } 43 | 44 | get _ewEntity() { 45 | return this._config.ewEntity || ""; 46 | } 47 | 48 | get _ewEntityJ1() { 49 | return this._config.ewEntityJ1 || ""; 50 | } 51 | 52 | get _ewEntityJ2() { 53 | return this._config.ewEntityJ2 || ""; 54 | } 55 | 56 | get _tempoEntity() { 57 | return this._config.tempoEntityInfo || ""; 58 | } 59 | 60 | get _tempoEntityJ0() { 61 | return this._config.tempoEntityJ0 || ""; 62 | } 63 | 64 | get _tempoEntityJ1() { 65 | return this._config.tempoEntityJ1 || ""; 66 | } 67 | 68 | get _name() { 69 | return this._config.name || ""; 70 | } 71 | 72 | get _showIcon() { 73 | return this._config.showIcon !== false; 74 | } 75 | 76 | get _showHeader() { 77 | return this._config.showHeader !== false; 78 | } 79 | 80 | get _showHistory() { 81 | return this._config.showHistory !== false; 82 | } 83 | 84 | get _showPeakOffPeak() { 85 | return this._config.showPeakOffPeak !== false; 86 | } 87 | 88 | get _showInTableUnit() { 89 | return this._config.showInTableUnit !== false; 90 | } 91 | 92 | get _showDayPrice() { 93 | return this._config.showDayPrice !== false; 94 | } 95 | 96 | get _showDayPriceHCHP() { 97 | return this._config.showDayPriceHCHP !== false; 98 | } 99 | 100 | get _showDayMaxPower() { 101 | return this._config.showDayMaxPower !== false; 102 | } 103 | 104 | get _showPrice() { 105 | return this._config.showPrice !== false; 106 | } 107 | 108 | get _showTitle() { 109 | return this._config.showTitle !== false; 110 | } 111 | 112 | get _showDayHCHP() { 113 | return this._config.showDayHCHP !== false; 114 | } 115 | 116 | get _showCurrentMonthRatio() { 117 | return this._config.showCurrentMonthRatio !== false; 118 | } 119 | 120 | get _showMonthRatio() { 121 | return this._config.showMonthRatio !== false; 122 | } 123 | 124 | get _showYearRatio() { 125 | return this._config.showYearRatio !== false; 126 | } 127 | 128 | get _showWeekRatio() { 129 | return this._config.showWeekRatio !== false; 130 | } 131 | 132 | get _showYesterdayRatio() { 133 | return this._config.showYesterdayRatio !== false; 134 | } 135 | get _showError() { 136 | return this._config.showError !== false; 137 | } 138 | get _showTitreLigne() { 139 | return this._config.showTitreLigne !== false; 140 | } 141 | get _showEcoWatt() { 142 | return this._config.showEcoWatt !== false; 143 | } 144 | get _showEcoWattJ12() { 145 | return this._config.showEcoWattJ12 !== false; 146 | } 147 | 148 | get _showTempo() { 149 | return this._config.showTempo !== false; 150 | } 151 | 152 | get _title() { 153 | return this._config.showTitle !== false; 154 | } 155 | 156 | get _current() { 157 | return this._config.current !== false; 158 | } 159 | 160 | get _details() { 161 | return this._config.details !== false; 162 | } 163 | 164 | get _nbJoursAffichage() { 165 | return this._config.nbJoursAffichage || 7; 166 | } 167 | 168 | get _showDayName() { 169 | return this._config.showDayName; 170 | } 171 | 172 | get _titleName() { 173 | return this._config.titleName || ""; 174 | } 175 | 176 | firstUpdated() { 177 | HELPERS.then(help => { 178 | if (help.importMoreInfoControl) { 179 | help.importMoreInfoControl("fan"); 180 | } 181 | }) 182 | } 183 | 184 | render() { 185 | if (!this.hass) { 186 | return html``; 187 | } 188 | 189 | return html` 190 |
191 |
192 | 198 | ${this.renderSensorPicker("Entity", this._entity, "entity")} 199 | ${this.renderSensorPicker("EcoWatt", this._ewEntity, "ewEntity")} 200 | ${this.renderSensorPicker("EcoWattJ1", this._ewEntityJ1, "ewEntityJ1")} 201 | ${this.renderSensorPicker("EcoWattJ2", this._ewEntityJ2, "ewEntityJ2")} 202 | ${this.renderSensorPicker("TempoInfo", this._tempoEntityInfo, "tempoEntityInfo")} 203 | ${this.renderSensorPicker("TempoJ0", this._tempoEntityJ0, "tempoEntityJ0")} 204 | ${this.renderSensorPicker("TempoJ1", this._tempoEntityJ1, "tempoEntityJ1")} 205 | 206 | 229 | 230 |
239 | 245 |
246 |
247 | `; 248 | } 249 | 250 | renderSensorPicker(label, entity, configAttr) { 251 | return this.renderPicker(label, entity, configAttr, "sensor"); 252 | } 253 | 254 | renderPicker(label, entity, configAttr, domain) { 255 | return html` 256 | 265 | ` 266 | } 267 | 268 | renderSwitchOption(label, state, configAttr) { 269 | return html` 270 |
  • 271 | 275 | ${label} 276 | 277 |
  • 278 | ` 279 | } 280 | _valueChanged(ev) { 281 | if (!this._config || !this.hass) { 282 | return; 283 | } 284 | const target = ev.target; 285 | if (target.configValue) { 286 | if (target.value === "") { 287 | delete this._config[target.configValue]; 288 | } else { 289 | this._config = { 290 | ...this._config, 291 | [target.configValue]: 292 | target.checked !== undefined ? target.checked : target.value, 293 | }; 294 | } 295 | } 296 | fireEvent(this, "config-changed", { config: this._config }); 297 | } 298 | 299 | static get styles() { 300 | return css` 301 | .switches { 302 | margin: 8px 0; 303 | display: flex; 304 | flex-flow: row wrap; 305 | list-style: none; 306 | padding: 0; 307 | } 308 | .switch { 309 | display: flex; 310 | align-items: center; 311 | width: 50%; 312 | height: 40px; 313 | } 314 | .switches span { 315 | padding: 0 16px; 316 | } 317 | `; 318 | } 319 | } 320 | 321 | customElements.define("content-card-linky-editor", contentCardLinkyEditor); 322 | -------------------------------------------------------------------------------- /dist/content-card-linky.js: -------------------------------------------------------------------------------- 1 | const LitElement = Object.getPrototypeOf( 2 | customElements.get("ha-panel-lovelace") 3 | ); 4 | const html = LitElement.prototype.html; 5 | const css = LitElement.prototype.css; 6 | 7 | 8 | window.customCards = window.customCards || []; 9 | window.customCards.push({ 10 | type: "content-card-linky", 11 | name: "Carte Enedis1", 12 | description: "Carte pour l'intégration myElectricalData.", 13 | preview: true, 14 | documentationURL: "https://github.com/saniho/content-card-linky", 15 | }); 16 | const fireEvent = (node, type, detail, options) => { 17 | options = options || {}; 18 | detail = detail === null || detail === undefined ? {} : detail; 19 | const event = new Event(type, { 20 | bubbles: options.bubbles === undefined ? true : options.bubbles, 21 | cancelable: Boolean(options.cancelable), 22 | composed: options.composed === undefined ? true : options.composed, 23 | }); 24 | event.detail = detail; 25 | node.dispatchEvent(event); 26 | return event; 27 | }; 28 | 29 | const ecoWattForecastValues = new Map([ 30 | ["Pas de valeur", "green"], 31 | [1, "green"], 32 | [2, "yellow"], 33 | [3, "red"], 34 | ]); 35 | 36 | const tempoValues = new Map([ 37 | ["unknown", "grey"], 38 | ["Inconnu", "grey"], 39 | ["BLUE", "blue"], 40 | ["WHITE", "white"], 41 | ["RED", "red"], 42 | ]); 43 | 44 | 45 | function hasConfigOrEntityChanged(element, changedProps) { 46 | if (changedProps.has("config")) { 47 | return true; 48 | } 49 | 50 | const oldHass = changedProps.get("hass"); 51 | if (oldHass) { 52 | return ( 53 | oldHass.states[element.config.entity] !== 54 | element.hass.states[element.config.entity] 55 | ); 56 | } 57 | 58 | return true; 59 | } 60 | 61 | class ContentCardLinky extends LitElement { 62 | static get properties() { 63 | return { 64 | config: {}, 65 | hass: {} 66 | }; 67 | } 68 | 69 | static async getConfigElement() { 70 | await import("./content-card-linky-editor.js"); 71 | return document.createElement("content-card-linky-editor"); 72 | } 73 | 74 | render() { 75 | if (!this.config || !this.hass) { 76 | return html``; 77 | } 78 | 79 | const stateObj = this.hass.states[this.config.entity]; 80 | 81 | if (!stateObj) { 82 | return html` 83 | 84 |
    85 |
    86 |
    87 | 88 | Linky : donnees inaccessible pour ${this.config.entity} 89 |
    90 |
    91 |
    92 |
    93 | ` 94 | } 95 | 96 | const attributes = stateObj.attributes; 97 | const modeCompteur = attributes["typeCompteur"]; 98 | 99 | if (stateObj) { 100 | if (( modeCompteur === "consommation" ) || ( !modeCompteur )){ 101 | return html` 102 | 103 | ${this.addEventListener('click', event => { this._showDetails(this.config.entity); })} 104 | ${this.renderTitle(this.config)} 105 |
    106 | ${this.renderHeader(attributes, this.config, stateObj)} 107 |
    108 | ${this.config.showYearRatio 109 | ? html ` 110 | 111 | 112 | 113 | 114 | 115 |
    116 | ${Math.round(attributes.yearly_evolution)} %par rapport à ${this.previousYear()} 117 | A-1 : ${attributes.current_year_last_year}
    A : ${attributes.current_year}
    118 |
    119 |
    ` 120 | : html `` 121 | } 122 | ${this.config.showMonthRatio 123 | ? html ` 124 | 125 | 126 | 127 | 128 | 129 |
    130 | ${Math.round(attributes.monthly_evolution)} %par rapport à ${this.previousMonth()} 131 | Mois Precedent A-1 : ${attributes.last_month_last_year}
    Mois Precedent : ${attributes.last_month}
    132 |
    133 |
    ` 134 | : html `` 135 | } 136 | ${this.config.showCurrentMonthRatio 137 | ? html ` 138 | 139 | 140 | 141 | 142 | 143 |
    144 | ${Math.round(attributes.current_month_evolution)} %par rapport à ${this.currentMonth()} 145 | Mois A-1 : ${attributes.current_month_last_year}
    Mois : ${attributes.current_month}
    146 |
    147 |
    ` 148 | : html `` 149 | } 150 | ${this.config.showWeekRatio 151 | ? html ` 152 | 153 | 154 | 155 | 156 | 157 |
    158 | ${Math.round(attributes.current_week_evolution)} %par rapport à ${this.weekBefore()} 159 | Semaine dernière : ${attributes.last_week}
    Semaine courante : ${attributes.current_week}
    160 |
    161 |
    ` 162 | : html `` 163 | } 164 | ${this.config.showYesterdayRatio 165 | ? html ` 166 | 167 | 168 | 169 | 170 | 171 |
    172 | ${Math.round(attributes.yesterday_evolution)} %par rapport à ${this.dayBeforeYesterday()} 173 | Avant-hier : ${attributes.day_2}
    Hier : ${attributes.yesterday}
    174 |
    175 |
    ` 176 | : html `` 177 | } 178 | ${this.config.showPeakOffPeak 179 | ? html ` 180 | 181 | 182 | 183 | 184 | ${Math.round(attributes.peak_offpeak_percent)} % HP 185 | ` 186 | : html `` 187 | } 188 | 189 |
    190 | ${this.renderHistory(attributes.daily, attributes.unit_of_measurement, attributes.dailyweek, attributes.dailyweek_cost, attributes.dailyweek_costHC, attributes.dailyweek_costHP, attributes.dailyweek_HC, attributes.dailyweek_HP, attributes.dailyweek_MP, attributes.dailyweek_MP_over, attributes.dailyweek_MP_time, this.config)} 191 | ${this.renderEcoWatt(attributes, this.config)} 192 | ${this.renderTempo(attributes, this.config)} 193 | ${this.renderError(attributes.errorLastCall, this.config)} 194 | ${this.renderVersion(attributes.versionUpdateAvailable, attributes.versionGit)} 195 | ${this.renderInformation(attributes, this.config)} 196 |
    197 |
    ` 198 | } 199 | if ( modeCompteur === "production" ){ 200 | return html` 201 | 202 |
    203 |
    204 | ${this.config.showIcon 205 | ? html` 206 |
    207 | 208 |
    ` 209 | : html `` 210 | } 211 |
    212 | ${this.toFloat(stateObj.state)} 213 | ${attributes.unit_of_measurement} 214 |
    215 |
    216 | ${this.renderError(attributes.errorLastCall, this.config)} 217 |
    218 |
    ` 219 | } 220 | } 221 | } 222 | _showDetails(myEntity) { 223 | const event = new Event('hass-more-info', { 224 | bubbles: true, 225 | cancelable: false, 226 | composed: true 227 | }); 228 | event.detail = { 229 | entityId: myEntity 230 | }; 231 | this.dispatchEvent(event); 232 | return event; 233 | } 234 | renderTitle(config) { 235 | if (this.config.showTitle === true) { 236 | return html 237 | ` 238 |
    239 |
    240 | ${this.config.titleName} 241 |
    242 |
    ` 243 | } 244 | } 245 | renderHeader(attributes, config, stateObj) { 246 | if (this.config.showHeader === true) { 247 | if( config.showPeakOffPeak ) { 248 | return html` 249 |
    250 | ${this.renderIcon(attributes, config)} 251 |
    252 | ${this.toFloat(attributes.yesterday_HC)} ${attributes.unit_of_measurement} (en HC)
    253 | ${this.toFloat(attributes.yesterday_HP)} ${attributes.unit_of_measurement} (en HP) 254 |
    255 | ${this.renderPrice(attributes, config)} 256 |
    ` 257 | } 258 | else{ 259 | return html` 260 |
    261 | ${this.renderIcon(attributes, config)} 262 |
    263 | ${this.toFloat(stateObj.state)} 264 | ${attributes.unit_of_measurement} 265 |
    266 | ${this.renderPrice(attributes, config)} 267 |
    ` 268 | } 269 | } 270 | } 271 | renderIcon(attributes, config) { 272 | if ( this.config.showIcon ){ 273 | return html ` 274 |
    275 | 276 |
    ` 277 | } 278 | else{ 279 | return html `` 280 | } 281 | } 282 | renderPrice(attributes, config) { 283 | if ( this.config.showPrice ){ 284 | return html ` 285 |
    286 | ${this.toFloat(attributes.daily_cost, 2)} 287 |
    ` 288 | } 289 | else{ 290 | return html `` 291 | } 292 | } 293 | renderError(errorMsg, config) { 294 | if (this.config.showError === true) { 295 | if ( errorMsg != "" ){ 296 | return html 297 | ` 298 |
    299 | 300 | ${errorMsg} 301 |
    302 | ` 303 | } 304 | } 305 | } 306 | renderInformation(attributes, config) { 307 | if (attributes.serviceEnedis === undefined ) { 308 | return html `` 309 | } 310 | else{ 311 | if ( attributes.serviceEnedis !== "myElectricalData" ){ 312 | return html ` 313 |
    314 | 315 | Merci de migrer sur myElectricalData.
    316 | EnedisGateway sera desactivé courant 2023. 317 |
    318 | ` 319 | } 320 | } 321 | } 322 | renderVersion(versionUpdateAvailable, versionGit) { 323 | if ( versionUpdateAvailable === true ){ 324 | return html 325 | ` 326 |
    327 | 328 | Nouvelle version disponible ${versionGit} 329 |
    330 | ` 331 | } 332 | else{ 333 | return html `` 334 | } 335 | } 336 | 337 | renderHistory(daily, unit_of_measurement, dailyweek, dailyweek_cost, dailyweek_costHC, dailyweek_costHP, dailyweek_HC, dailyweek_HP, dailyweek_MP, dailyweek_MP_over, dailyweek_MP_time, config) { 338 | if (this.config.showHistory === true) { 339 | if ( dailyweek != undefined){ 340 | var nbJours = dailyweek.toString().split(",").length ; 341 | if ( config.nbJoursAffichage <= nbJours ) { nbJours = config.nbJoursAffichage } 342 | return html 343 | ` 344 |
    345 | ${this.renderTitreLigne(config)} 346 | ${daily.slice(0, nbJours).reverse().map((day, index) => this.renderDay(day, nbJours-index, unit_of_measurement, dailyweek, dailyweek_cost, dailyweek_costHC, dailyweek_costHP, 347 | dailyweek_HC, dailyweek_HP, dailyweek_MP, dailyweek_MP_over, dailyweek_MP_time, config))} 348 |
    349 | ` 350 | } 351 | } 352 | } 353 | 354 | renderDay(day, dayNumber, unit_of_measurement, dailyweek, dailyweek_cost, dailyweek_costHC, dailyweek_costHP, dailyweek_HC, dailyweek_HP, dailyweek_MP, dailyweek_MP_over, dailyweek_MP_time, config) { 355 | return html 356 | ` 357 |
    358 | ${this.renderDailyWeek(dailyweek, dayNumber, config)} 359 | ${this.renderDailyValue(day, dayNumber, unit_of_measurement, config)} 360 | ${this.renderDayPrice(dailyweek_cost, dayNumber, config)} 361 | ${this.renderDayPriceHCHP(dailyweek_costHC, dayNumber, config)} 362 | ${this.renderDayPriceHCHP(dailyweek_costHP, dayNumber, config)} 363 | ${this.renderDayHCHP(dailyweek_HC, dayNumber, unit_of_measurement, config)} 364 | ${this.renderDayHCHP(dailyweek_HP, dayNumber, unit_of_measurement, config)} 365 | ${this.renderDayMaxPower(dailyweek_MP, dayNumber, dailyweek_MP_over, dailyweek_MP_time, config)} 366 |
    367 | ` 368 | } 369 | renderDailyWeekTitre( maConfig, monTitre ){ 370 | if (maConfig === true) { 371 | return html 372 | `${monTitre}
    373 | ` 374 | } 375 | else{ 376 | return html 377 | ` 378 | ` 379 | } 380 | } 381 | renderTitreLigne(config) { 382 | if (this.config.showTitreLigne === true) { 383 | return html 384 | ` 385 |
    386 | ${this.renderDailyWeekTitre(true, "")} 387 | ${this.renderDailyWeekTitre(true, "Conso")} 388 | ${this.renderDailyWeekTitre(this.config.showDayPrice, "Prix")} 389 | ${this.renderDailyWeekTitre(this.config.showDayPriceHCHP, "Prix HC")} 390 | ${this.renderDailyWeekTitre(this.config.showDayPriceHCHP, "Prix HP")} 391 | ${this.renderDailyWeekTitre(this.config.showDayHCHP, "HC")} 392 | ${this.renderDailyWeekTitre(this.config.showDayHCHP, "HP")} 393 | ${this.renderDailyWeekTitre(this.config.showDayMaxPower, "MP")} 394 | ${this.renderDailyWeekTitre(this.config.showDayMaxPowerTime, "MPtime")} 395 |
    396 | ` 397 | } 398 | } 399 | r_enderTitreLigne(config) { 400 | if (this.config.showTitreLigne === true) { 401 | return html 402 | ` 403 |
    404 |
    Conso. 405 | ${this.config.showDayPrice 406 | ? html ` 407 |
    Prix` 408 | : html `` 409 | } 410 | ${this.config.showDayPriceHCHP 411 | ? html ` 412 |
    Prix HC` 413 | : html `` 414 | } 415 | ${this.config.showDayPriceHCHP 416 | ? html ` 417 |
    Prix HP` 418 | : html `` 419 | } 420 | ${this.config.showDayHCHP 421 | ? html ` 422 |
    HC` 423 | : html `` 424 | } 425 | ${this.config.showDayHCHP 426 | ? html ` 427 |
    HP` 428 | : html `` 429 | } 430 | ${this.config.showDayMaxPower 431 | ? html ` 432 |
    MP` 433 | : html `` 434 | } 435 | ${this.config.showDayMaxPower 436 | ? html ` 437 |
    MPtime` 438 | : html `` 439 | } 440 |
    441 | `; 442 | } 443 | } 444 | renderDailyWeek(value, dayNumber, config) { 445 | return html 446 | ` 447 | ${new Date(value.toString().split(",")[dayNumber-1]).toLocaleDateString('fr-FR', {weekday: config.showDayName})} 448 | `; 449 | } 450 | renderNoData(){ 451 | return html 452 | ` 453 |
    454 | ` ; 455 | } 456 | renderDailyValue(day, dayNumber, unit_of_measurement, config) { 457 | if ( day === -1 ){ 458 | return this.renderNoData(); 459 | } 460 | else{ 461 | return html 462 | ` 463 |
    ${this.toFloat(day)} 464 | ${this.config.showInTableUnit 465 | ? html ` 466 | ${unit_of_measurement}` 467 | : html `` 468 | } 469 | `; 470 | } 471 | } 472 | renderDayPrice(value, dayNumber, config) { 473 | if (config.kWhPrice) { 474 | return html 475 | ` 476 |
    ${this.toFloat(value * config.kWhPrice, 2)} € 477 | `; 478 | } 479 | if (config.showDayPrice) { 480 | const valeur = value.toString().split(",")[dayNumber-1] ; 481 | if ( valeur === "-1" ){ 482 | return this.renderNoData(); 483 | } 484 | else{ 485 | return html 486 | ` 487 |
    ${this.toFloat(valeur)} € 488 | `; 489 | } 490 | } 491 | } 492 | renderDayPriceHCHP(value, dayNumber, config) { 493 | if (config.showDayPriceHCHP) { 494 | const valeur = value.toString().split(",")[dayNumber-1] ; 495 | if ( valeur === "-1" ){ 496 | return this.renderNoData(); 497 | } 498 | else{ 499 | return html 500 | ` 501 |
    ${this.toFloat(valeur, 2)} € 502 | `; 503 | } 504 | } 505 | } 506 | renderDayHCHP(value, dayNumber, unit_of_measurement, config) { 507 | if (config.showDayHCHP) { 508 | const valeur = value.toString().split(",")[dayNumber-1] ; 509 | if ( valeur === "-1" ){ 510 | return this.renderNoData(); 511 | } 512 | else{ 513 | return html 514 | ` 515 |
    ${this.toFloat(valeur, 2)} 516 | ${this.config.showInTableUnit 517 | ? html ` 518 | ${unit_of_measurement}` 519 | : html `` 520 | } 521 | `; 522 | } 523 | } 524 | } 525 | renderDayMaxPower(value, dayNumber, overMP, MPtime, config) { 526 | if (config.showDayMaxPower) { 527 | const valeur = value.toString().split(",")[dayNumber-1] ; 528 | const over = overMP.toString().split(",")[dayNumber-1]; 529 | if ( valeur === "-1" ){ 530 | return this.renderNoData(); 531 | } 532 | else{ 533 | if ( over === "true") { 534 | return html 535 | ` 536 |
    ${this.toFloat(valeur, 2)} 537 |
    ${new Date(MPtime.toString().split(",")[dayNumber-1]).toLocaleTimeString('fr-FR', { hour: "2-digit", minute: "2-digit" }) } 538 | `; 539 | } 540 | else { 541 | return html 542 | ` 543 |
    ${this.toFloat(valeur, 2)} 544 |
    ${new Date(MPtime.toString().split(",")[dayNumber-1]).toLocaleTimeString('fr-FR', { hour: "2-digit", minute: "2-digit" }) } 545 | `; 546 | } 547 | } 548 | } 549 | } 550 | 551 | renderDayMaxPowerTime(value, dayNumber, overMP, config) { 552 | if (config.showDayMaxPower) { 553 | const valeur = value.toString.split(",")[dayNumber-1] ; 554 | const over = overMP.toString().split(",")[dayNumber-1]; 555 | if ( valeur === "-1" ){ 556 | return this.renderNoData(); 557 | } 558 | else{ 559 | if ( over === "true") { 560 | return html 561 | ` 562 |
    ${this.toFloat(valeur, 2)} 563 | `; 564 | } 565 | else { 566 | return html 567 | ` 568 |
    ${this.toFloat(valeur, 2)} 569 | `; 570 | } 571 | } 572 | } 573 | } 574 | 575 | getOneDayForecastTime(ecoWattForecast) { 576 | let ecoWattForecastDate = new Date(ecoWattForecast.attributes["date"]); 577 | return [ecoWattForecastDate]; 578 | } 579 | 580 | getOneDayNextEcoWattText(ecoWattForecastEntity) { 581 | let forecastDate = new Date(ecoWattForecastEntity.attributes["date"]); 582 | for (let [time, value] of Object.entries( 583 | ecoWattForecastEntity.attributes["forecast"] 584 | )) { 585 | if ( time != undefined && ecoWattForecastValues.get(value) !== "green" ) { 586 | let timeStr = time.replace(/([345])5/g, "$10"); 587 | return html `Actuellement: ${ecoWattForecastValues.get(value)}`; 588 | } else 589 | { 590 | return html `Ecowatt ${ forecastDate.toLocaleDateString('fr-FR', {weekday: 'long', day: 'numeric'}) }`; 591 | } 592 | } 593 | return "" 594 | } 595 | 596 | getOneDayNextEcoWatt(ecoWattForecastEntity) { 597 | let ecoWattForecastList = []; 598 | for (let [time, value] of Object.entries( 599 | ecoWattForecastEntity.attributes["forecast"] 600 | )) { 601 | if (time != undefined) { 602 | time = time.replace("h", "").trim(); 603 | time = time.replace("min", "").trim(); 604 | ecoWattForecastList.push([time, ecoWattForecastValues.get(value), value]); 605 | } 606 | } 607 | 608 | return ecoWattForecastList; 609 | } 610 | 611 | renderEcoWatt(attributes, config) { 612 | if (attributes.serviceEnedis === undefined ){ 613 | return html ``; 614 | } 615 | if ( attributes.serviceEnedis !== "myElectricalData" ){ 616 | return html `EcoWatt : uniquement disponible avec myElectricData`; 617 | } 618 | 619 | let sensorName = this.config.ewEntity; 620 | const ecoWattForecast = this.hass.states[sensorName]; 621 | let sensorNameJ1 = this.config.ewEntityJ1; 622 | const ecoWattForecastJ1 = this.hass.states[sensorNameJ1]; 623 | let sensorNameJ2 = this.config.ewEntityJ2; 624 | const ecoWattForecastJ2 = this.hass.states[sensorNameJ2]; 625 | 626 | return html` 627 | 628 | ${this.config.showEcoWatt 629 | ? html` 630 | 631 | 632 | 642 | ` 643 | : html ``} 644 | ${this.config.showEcoWattJ12 645 | ? html` 646 | 647 | 648 | 658 | 659 | 660 | 661 | 671 | 672 | 673 | 674 | 684 | 685 | ` 686 | : html``} 687 | `; 688 | } 689 | 690 | getTempoDateValue(tempoEntity) { 691 | let tempoDate = new Date(tempoEntity.attributes["date"]); 692 | let tempoValue = tempoEntity.state; 693 | return [tempoDate, tempoValues.get(tempoValue), tempoValue]; 694 | } 695 | 696 | getTempoRemainingDays(tempoEntity) { 697 | let tempoRemainingRed = tempoEntity.attributes["days_red"]; 698 | let tempoRemainingWhite = tempoEntity.attributes["days_white"]; 699 | let tempoRemainingBlue = tempoEntity.attributes["days_blue"]; 700 | return [tempoRemainingRed, tempoRemainingWhite, tempoRemainingBlue]; 701 | } 702 | 703 | renderTempo(attributes, config) { 704 | if (attributes.serviceEnedis === undefined ){ 705 | return html ``; 706 | } 707 | if ( attributes.serviceEnedis !== "myElectricalData" ){ 708 | return html `EcoWatt : uniquement disponible avec myElectricData`; 709 | } 710 | if (this.config.showTempo === false ){ 711 | return html ``; 712 | } 713 | let sensorName = this.config.tempoEntityInfo; 714 | const tempoInfo = this.hass.states[sensorName]; 715 | let sensorNameJ0 = this.config.tempoEntityJ0; 716 | const tempoJ0 = this.hass.states[sensorNameJ0]; 717 | let sensorNameJ1 = this.config.tempoEntityJ1; 718 | const tempoJ1 = this.hass.states[sensorNameJ1]; 719 | 720 | if (!tempoJ0 || tempoJ0.length === 0 || !tempoJ1 || tempoJ1.length === 0) { 721 | return html `Tempo: sensor(s) J0 et/ou J1 indisponible ou incorrecte`; 722 | } 723 | if (!tempoInfo || tempoInfo.length === 0) { 724 | return html `Tempo: sensor 'info' indisponible ou incorrecte`; 725 | } 726 | 727 | let [dateJ0, valueJ0, stateJ0] = this.getTempoDateValue(tempoJ0); 728 | let [dateJ1, valueJ1, stateJ1] = this.getTempoDateValue(tempoJ1); 729 | let [remainingRed, remainingWhite, remainingBlue] = this.getTempoRemainingDays(tempoInfo); 730 | 731 | return html` 732 |
    J+0 633 |
      634 | ${html` 635 | ${this.getOneDayNextEcoWatt(ecoWattForecast).map( 636 | (forecast) => html` 637 |
    • ` 638 | )} 639 | `} 640 |
    641 |
    J+1 649 |
      650 | ${html` 651 | ${this.getOneDayNextEcoWatt(ecoWattForecastJ1).map( 652 | (forecast) => html` 653 |
    • ` 654 | )} 655 | `} 656 |
    657 |
    J+2 662 |
      663 | ${html` 664 | ${this.getOneDayNextEcoWatt(ecoWattForecastJ2).map( 665 | (forecast) => html` 666 |
    • ` 667 | )} 668 | `} 669 |
    670 |
    675 |
      676 | ${html` 677 | ${this.getOneDayNextEcoWatt(ecoWattForecastJ2).map( 678 | (forecast) => html` 679 |
    • ${(forecast[0]%2==1) ? forecast[0] : ''}
    • ` 680 | )} 681 | `} 682 |
    683 |
    733 | 734 | 735 | 736 | 737 |
    ${ (new Date(dateJ0)).toLocaleDateString('fr-FR', {weekday: 'long', day: 'numeric'})}${ (new Date(dateJ1)).toLocaleDateString('fr-FR', {weekday: 'long', day: 'numeric'})}
    738 | 739 | 740 | 741 | 742 | 743 | 744 |
    ${remainingBlue}${remainingWhite}${remainingRed}
    745 | 746 | ` 747 | 748 | } 749 | 750 | setConfig(config) { 751 | if (!config.entity) { 752 | throw new Error('You need to define an entity'); 753 | } 754 | 755 | if (config.kWhPrice && isNaN(config.kWhPrice)) { 756 | throw new Error('kWhPrice should be a number') 757 | } 758 | 759 | const defaultConfig = { 760 | showHistory: true, 761 | showHeader: true, 762 | showPeakOffPeak: true, 763 | showIcon: false, 764 | showInTableUnit: false, 765 | showDayPrice: false, 766 | showDayPriceHCHP: false, 767 | showDayMaxPower: false, 768 | showDayHCHP: false, 769 | showDayName: "long", 770 | showError: true, 771 | shoInformation: true, 772 | showPrice: true, 773 | showTitle: false, 774 | showCurrentMonthRatio: true, 775 | showMonthRatio: true, 776 | showWeekRatio: false, 777 | showYesterdayRatio: false, 778 | showTitreLigne: false, 779 | showEcoWatt: false, 780 | showEcoWattJ12: false, 781 | showTempo: false, 782 | titleName: "", 783 | nbJoursAffichage: 7, 784 | kWhPrice: undefined, 785 | } 786 | 787 | this.config = { 788 | ...defaultConfig, 789 | ...config 790 | }; 791 | } 792 | 793 | shouldUpdate(changedProps) { 794 | return hasConfigOrEntityChanged(this, changedProps); 795 | } 796 | 797 | // @TODO: This requires more intelligent logic 798 | getCardSize() { 799 | return 3; 800 | } 801 | 802 | toFloat(value, decimals = 1) { 803 | return Number.parseFloat(value).toFixed(decimals); 804 | } 805 | 806 | previousYear() { 807 | var d = new Date(); 808 | d.setFullYear(d.getFullYear()-1 ); 809 | 810 | return d.toLocaleDateString('fr-FR', {year: "numeric"}); 811 | } 812 | 813 | previousMonth() { 814 | var d = new Date(); 815 | d.setMonth(d.getMonth()-1) ; 816 | d.setFullYear(d.getFullYear()-1 ); 817 | 818 | return d.toLocaleDateString('fr-FR', {month: "long", year: "numeric"}); 819 | } 820 | currentMonth() { 821 | var d = new Date(); 822 | d.setFullYear(d.getFullYear()-1 ); 823 | 824 | return d.toLocaleDateString('fr-FR', {month: "long", year: "numeric"}); 825 | } 826 | weekBefore() { 827 | return "semaine"; 828 | } 829 | dayBeforeYesterday() { 830 | return "avant-hier"; 831 | } 832 | 833 | 834 | static get styles() { 835 | return css` 836 | .card { 837 | margin: auto; 838 | padding: 1.5em 1em 1em 1em; 839 | position: relative; 840 | cursor: pointer; 841 | } 842 | 843 | ha-card ul { 844 | list-style: none; 845 | padding: 0; 846 | margin: 0; 847 | } 848 | 849 | .main-title { 850 | margin: auto; 851 | text-align: center; 852 | font-weight: 200; 853 | font-size: 2em; 854 | justify-content: space-between; 855 | } 856 | .main-info { 857 | display: flex; 858 | overflow: hidden; 859 | align-items: center; 860 | justify-content: space-between; 861 | height: 75px; 862 | } 863 | 864 | .ha-icon { 865 | margin-right: 5px; 866 | color: var(--paper-item-icon-color); 867 | } 868 | 869 | .cout-block { 870 | } 871 | 872 | .cout { 873 | font-weight: 300; 874 | font-size: 3.5em; 875 | } 876 | 877 | .cout-unit { 878 | font-weight: 300; 879 | font-size: 1.2em; 880 | display: inline-block; 881 | } 882 | 883 | .conso-hp, .conso-hc { 884 | font-weight: 200; 885 | font-size: 2em; 886 | } 887 | 888 | .conso-unit-hc, .conso-unit-hp { 889 | font-weight: 100; 890 | font-size: 1em; 891 | } 892 | 893 | .more-unit { 894 | font-style: italic; 895 | font-size: 0.8em; 896 | } 897 | 898 | .variations { 899 | display: flex; 900 | justify-content: space-between; 901 | overflow: hidden; 902 | } 903 | 904 | .variations-linky { 905 | display: inline-block; 906 | font-weight: 300; 907 | margin: 0px 0px 5px; 908 | overflow: hidden; 909 | } 910 | 911 | .unit { 912 | font-size: .8em; 913 | } 914 | 915 | .week-history { 916 | display: flex; 917 | overflow: hidden; 918 | } 919 | 920 | .day { 921 | flex: auto; 922 | text-align: center; 923 | border-right: .1em solid var(--divider-color); 924 | line-height: 2; 925 | box-sizing: border-box; 926 | } 927 | 928 | .dayname { 929 | font-weight: bold; 930 | text-transform: capitalize; 931 | } 932 | 933 | .week-history .day:last-child { 934 | border-right: none; 935 | } 936 | 937 | .cons-val { 938 | //font-weight: bold; 939 | } 940 | 941 | .year { 942 | font-size: 0.8em; 943 | font-style: italic; 944 | margin-left: 5px; 945 | } 946 | .previous-month { 947 | font-size: 0.8em; 948 | font-style: italic; 949 | margin-left: 5px; 950 | } 951 | .current-month { 952 | font-size: 0.8em; 953 | font-style: italic; 954 | margin-left: 5px; 955 | } 956 | .icon-block { 957 | } 958 | .linky-icon.bigger { 959 | width: 6em; 960 | height: 5em; 961 | display: inline-block; 962 | } 963 | .error { 964 | font-size: 0.8em; 965 | font-style: bold; 966 | margin-left: 5px; 967 | } 968 | .tooltip .tooltiptext { 969 | visibility: hidden; 970 | background: var( --ha-card-background, var(--card-background-color, white) ); 971 | box-shadow: 2px 2px 6px -4px #999; 972 | cursor: default; 973 | font-size: 14px; 974 | opacity: 1; 975 | pointer-events: none; 976 | position: absolute; 977 | display: flex; 978 | flex-direction: column; 979 | overflow: hidden; 980 | z-index: 12; 981 | transition: 0.15s ease all; 982 | padding: 5px; 983 | border: 1px solid #cecece; 984 | border-radius: 3px; 985 | } 986 | .tooltip .tooltiptext::after { 987 | content: ""; 988 | position: absolute; 989 | top: 100%; 990 | left: 50%; 991 | margin-left: -5px; 992 | border-width: 5px; 993 | border-style: solid; 994 | border-color: #555 transparent transparent transparent; 995 | } 996 | .tooltip:hover .tooltiptext { 997 | visibility: visible; 998 | opacity: 1; 999 | } 1000 | 1001 | .flow-row { 1002 | display: flex; 1003 | flex-flow: row wrap; 1004 | } 1005 | /* One Hour Forecast */ 1006 | .oneHour { 1007 | height: 1em; 1008 | } 1009 | .oneHour > li { 1010 | background-color: var(--paper-item-icon-color); 1011 | border-right: 1px solid var(--lovelace-background, var(--primary-background-color)); 1012 | } 1013 | .oneHour > li:first-child { 1014 | border-top-left-radius: 5px; 1015 | border-bottom-left-radius: 5px; 1016 | } 1017 | .oneHour > li:last-child { 1018 | border-top-right-radius: 5px; 1019 | border-bottom-right-radius: 5px; 1020 | border: 0; 1021 | } 1022 | /* One Hour Labels */ 1023 | .ecowatt-00, .ecowatt-01, .ecowatt-02, .ecowatt-03, .ecowatt-04, .ecowatt-05, .ecowatt-06, .ecowatt-07{ 1024 | flex: 2 1 0; 1025 | } 1026 | .ecowatt-08, .ecowatt-09, .ecowatt-10, .ecowatt-11, .ecowatt-12, .ecowatt-13, .ecowatt-14, .ecowatt-15 { 1027 | flex: 2 1 0; 1028 | } 1029 | .ecowatt-16, .ecowatt-17, .ecowatt-18, .ecowatt-19, .ecowatt-20, .ecowatt-21, .ecowatt-22, .ecowatt-23 { 1030 | flex: 2 1 0; 1031 | } 1032 | 1033 | .oneHourLabel > li:first-child { 1034 | flex: 0.70 1 0; 1035 | } 1036 | .oneHourLabel > li { 1037 | flex: 1 1 0; 1038 | text-align: left; 1039 | } 1040 | /* One Hour Header */ 1041 | .oneHourHeader { 1042 | justify-content: space-between; 1043 | } 1044 | .oneHourHeader li:last-child { 1045 | text-align: right; 1046 | } 1047 | .tempo-days { 1048 | width:100%; 1049 | border-spacing: 2px; 1050 | } 1051 | .tempo-color { 1052 | width:100%; 1053 | border-spacing: 2px; 1054 | } 1055 | .tempo-blue { 1056 | color: white; 1057 | text-align: center; 1058 | background: #009dfa; 1059 | border: 2px solid var(--divider-color); 1060 | box-shadow: var(--ha-card-box-shadow,none); 1061 | 1062 | } 1063 | .tempo-white { 1064 | color: #002654; 1065 | text-align: center; 1066 | background: white; 1067 | border: 2px solid var(--divider-color); 1068 | box-shadow: var(--ha-card-box-shadow,none); 1069 | 1070 | } 1071 | .tempo-red { 1072 | color: white; 1073 | text-align: center; 1074 | background: #ff2700; 1075 | border: 2px solid var(--divider-color); 1076 | box-shadow: var(--ha-card-box-shadow,none); 1077 | } 1078 | .tempo-grey { 1079 | color: white; 1080 | text-align: center; 1081 | background: grey; 1082 | border: 2px solid var(--divider-color); 1083 | box-shadow: var(--ha-card-box-shadow,none); 1084 | background-image: linear-gradient(45deg, #d6d6d6 25%, #dedede 25%, #dedede 50%, #d6d6d6 50%, #d6d6d6 75%, #dedede 75%, #dedede 100%); 1085 | background-size: 28.28px 28.28px; 1086 | } 1087 | `; 1088 | } 1089 | } 1090 | customElements.define('content-card-linky', ContentCardLinky); 1091 | --------------------------------------------------------------------------------