const LitElement = Object.getPrototypeOf( customElements.get("ha-panel-lovelace") ); const html = LitElement.prototype.html; const weatherIconsDay = { clear: "day", "clear-night": "day", "nuit claire": "day", cloudy: "cloudy", fog: "cloudy", hail: "rainy-7", lightning: "thunder", "lightning-rainy": "thunder", partlycloudy: "cloudy-day-3", pouring: "rainy-6", rainy: "rainy-5", snowy: "snowy-6", "snowy-rainy": "rainy-7", sunny: "day", windy: "cloudy", "windy-variant": "cloudy-day-3", exceptional: "!!" }; const weatherIconsNight = { ...weatherIconsDay, clear: "night", "clear-night": "night", sunny: "night", "nuit claire": "night", partlycloudy: "cloudy-night-3", "windy-variant": "cloudy-night-3" }; const fireEvent = (node, type, detail, options) => { options = options || {}; detail = detail === null || detail === undefined ? {} : detail; const event = new Event(type, { bubbles: options.bubbles === undefined ? true : options.bubbles, cancelable: Boolean(options.cancelable), composed: options.composed === undefined ? true : options.composed }); event.detail = detail; node.dispatchEvent(event); return event; }; function getWindDirectionRotation(direction) { let windDirections = [ "N",//0 "NNE", "NE", "ENE", "E",//90 "ESE", "SE", "SSE", "S",//180 "SSO", "SO", "OSO", "O",//270 "ONO", "NO", "NNO" ]; let name = windDirections[Math.round(direction/22.5)%16]; return name; } function getVigilance(color, alertEntity) { let phenomenaIcons = { "Vent violent": "mdi:weather-windy", "Pluie-inondation": "mdi:weather-pouring", "Orages": "mdi:weather-lightning", "Inondation": "mdi:home-flood", "Neige-verglas": "mdi:weather-snowy-heavy", "Canicule": "mdi:weather-sunny-alert", "Grand-froid": "mdi:snowflake", "Avalanches": "mdi:image-filter-hdr", "Vagues-submersion": "mdi:waves" }; if(alertEntity == undefined) { return []; } let phenomenaList = []; for (const [currentPhenomenon, currentPhenomenonColor] of Object.entries(alertEntity.attributes)) { if(currentPhenomenonColor == color) { phenomenaList.push([currentPhenomenon, phenomenaIcons[currentPhenomenon]]); } } return phenomenaList; } function getRainForecast(rainForecastEntity) { let rainForecastColors = new Map([ ['Temps sec', 0.1], ['Pluie faible', 0.4], ['Pluie modérée', 0.7], ['Pluie forte', 1] ]); let rainForecastList = []; for (let [time, value] of Object.entries(rainForecastEntity.attributes['1_hour_forecast'])) { if(time != undefined && time.match(/[0-9]*min/g)) { time = time.replace('min', '').trim(); rainForecastList.push([time, rainForecastColors.get(value), value]); } } return rainForecastList; } function hasConfigOrEntityChanged(element, changedProps) { if (changedProps.has("_config")) { return true; } const oldHass = changedProps.get("hass"); if (oldHass) { return ( oldHass.states[element._config.entity] !== element.hass.states[element._config.entity] || oldHass.states["sun.sun"] !== element.hass.states["sun.sun"] ); } return true; } class WeatherCard extends LitElement { static get properties() { return { _config: {}, hass: {} }; } static async getConfigElement() { await import("./meteo-france-weather-card-editor.js"); return document.createElement("meteo-france-weather-card-editor"); } static getStubConfig() { return {}; } setConfig(config) { if (!config.entity) { throw new Error("Please define a weather entity"); } this._config = config; } shouldUpdate(changedProps) { return hasConfigOrEntityChanged(this, changedProps); } render() { if (!this._config || !this.hass) { return html``; } const stateObj = this.hass.states[this._config.entity]; const rainChanceObj = this.hass.states[this._config.rainChanceEntity]; const cloudCoverObj = this.hass.states[this._config.cloudCoverEntity]; const snowChanceObj = this.hass.states[this._config.snowChanceEntity]; const freezeChanceObj = this.hass.states[this._config.freezeChanceEntity]; const alertObj = this.hass.states[this._config.alertEntity]; const rainForecastObj = this.hass.states[this._config.rainForecastEntity]; const uvObj = this.hass.states[this._config.uvEntity]; if (!stateObj) { return html`
Entity not available: ${this._config.entity}
`; } const lang = this.hass.selectedLanguage || this.hass.language; const next_rising = new Date( this.hass.states["sun.sun"].attributes.next_rising ); const next_setting = new Date( this.hass.states["sun.sun"].attributes.next_setting ); return html` ${this.renderStyle()} ${stateObj.state} ${ this._config.name ? html` ${this._config.name} ` : "" } ${ this.getUnit("temperature") == "°F" ? Math.round(stateObj.attributes.temperature) : stateObj.attributes.temperature } ${this.getUnit("temperature")} ${ rainForecastObj != undefined ? html`
${ html` ${ getRainForecast(rainForecastObj).map( forecast => html`
` ) } ` }
` : "" } ${ getVigilance("Jaune", alertObj).length > 0 ? html` Vigilance jaune en cours
${ getVigilance("Jaune", alertObj).map( phenomenon => html` ` ) }
` : "" } ${ getVigilance("Orange", alertObj).length > 0 ? html` Vigilance orange en cours
${ getVigilance("Orange", alertObj).map( phenomenon => html` ` ) }
` : "" } ${ getVigilance("Rouge", alertObj).length > 0 ? html` Vigilance rouge en cours
${ getVigilance("Rouge", alertObj).map( phenomenon => html` ` ) }
` : "" } ${ stateObj.attributes.forecast && stateObj.attributes.forecast.length > 0 ? html`
${ stateObj.attributes.forecast.slice(0, 5).map( daily => html`
${ new Date(daily.datetime).toLocaleDateString( lang, { weekday: "short" } ) }

${daily.temperature}${ this.getUnit("temperature") } ${ typeof daily.templow !== 'undefined' ? html`
${daily.templow}${ this.getUnit("temperature") } ` : "" } ${ typeof daily.precipitation !== 'undefined' ? html`
${daily.precipitation}${ this.getUnit("precipitation") } ` : "" }
` ) }
` : "" }
`; } getWeatherIcon(condition, sun) { let icon = `${ this._config.icons ? this._config.icons : "https://cdn.jsdelivr.net/gh/bramkragten/custom-ui@master/weather-card/icons/animated/" }${ sun && sun == "below_horizon" ? weatherIconsNight[condition] : weatherIconsDay[condition] }.svg`; return icon; } getUnit(measure) { const lengthUnit = this.hass.config.unit_system.length; switch (measure) { case "air_pressure": return lengthUnit === "km" ? "hPa" : "inHg"; case "length": return lengthUnit; case "precipitation": return lengthUnit === "km" ? "mm" : "in"; default: return this.hass.config.unit_system[measure] || ""; } } _handleClick() { fireEvent(this, "hass-more-info", { entityId: this._config.entity }); } getCardSize() { return 3; } renderStyle() { return html` `; } } customElements.define("meteo-france-weather-card", WeatherCard);