+
+ ${oo("common.not_available")}
+
+
+
+
+ `;const{state:t}=this.entity,{battery_level:e,battery_icon:a}=this.getAttributes(this.entity);return K`
+
+ this.handleMore()}"
+ ?more-info="true"
+ >
+
+
+ ${this.renderMapOrImage(t)}
+
+
+ ${this.renderName()} ${this.renderStatus()}
+
+
+
+ ${this.renderStats(t)}
+
+
+
+ ${this.renderToolbar(t)}
+
+ `}}),window.customCards=window.customCards||[],window.customCards.push({preview:!0,type:"vacuum-card",name:oo("common.name"),description:oo("common.description")});
diff --git a/www/lovelace/custom/weather-card/icons/cloudy-day-1.svg b/www/lovelace/custom/weather-card/icons/cloudy-day-1.svg
new file mode 100644
index 0000000..c1f1922
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/cloudy-day-1.svg
@@ -0,0 +1,175 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/cloudy-day-2.svg b/www/lovelace/custom/weather-card/icons/cloudy-day-2.svg
new file mode 100644
index 0000000..712a564
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/cloudy-day-2.svg
@@ -0,0 +1,176 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/cloudy-day-3.svg b/www/lovelace/custom/weather-card/icons/cloudy-day-3.svg
new file mode 100644
index 0000000..ddcd408
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/cloudy-day-3.svg
@@ -0,0 +1,175 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/cloudy-night-1.svg b/www/lovelace/custom/weather-card/icons/cloudy-night-1.svg
new file mode 100644
index 0000000..bc6360d
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/cloudy-night-1.svg
@@ -0,0 +1,198 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/cloudy-night-2.svg b/www/lovelace/custom/weather-card/icons/cloudy-night-2.svg
new file mode 100644
index 0000000..391ceeb
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/cloudy-night-2.svg
@@ -0,0 +1,198 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/cloudy-night-3.svg b/www/lovelace/custom/weather-card/icons/cloudy-night-3.svg
new file mode 100644
index 0000000..2425af9
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/cloudy-night-3.svg
@@ -0,0 +1,198 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/cloudy.svg b/www/lovelace/custom/weather-card/icons/cloudy.svg
new file mode 100644
index 0000000..d94fd30
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/cloudy.svg
@@ -0,0 +1,500 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/day.svg b/www/lovelace/custom/weather-card/icons/day.svg
new file mode 100644
index 0000000..6566b16
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/day.svg
@@ -0,0 +1,521 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/night.svg b/www/lovelace/custom/weather-card/icons/night.svg
new file mode 100644
index 0000000..0c13686
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/night.svg
@@ -0,0 +1,503 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/rainy-1.svg b/www/lovelace/custom/weather-card/icons/rainy-1.svg
new file mode 100644
index 0000000..575df6c
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/rainy-1.svg
@@ -0,0 +1,157 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/rainy-2.svg b/www/lovelace/custom/weather-card/icons/rainy-2.svg
new file mode 100644
index 0000000..faa8cf0
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/rainy-2.svg
@@ -0,0 +1,133 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/rainy-3.svg b/www/lovelace/custom/weather-card/icons/rainy-3.svg
new file mode 100644
index 0000000..bfb2a4c
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/rainy-3.svg
@@ -0,0 +1,157 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/rainy-4.svg b/www/lovelace/custom/weather-card/icons/rainy-4.svg
new file mode 100644
index 0000000..52252b4
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/rainy-4.svg
@@ -0,0 +1,66 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/rainy-5.svg b/www/lovelace/custom/weather-card/icons/rainy-5.svg
new file mode 100644
index 0000000..52461db
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/rainy-5.svg
@@ -0,0 +1,90 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/rainy-6.svg b/www/lovelace/custom/weather-card/icons/rainy-6.svg
new file mode 100644
index 0000000..ea384b1
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/rainy-6.svg
@@ -0,0 +1,91 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/rainy-7.svg b/www/lovelace/custom/weather-card/icons/rainy-7.svg
new file mode 100644
index 0000000..220dcf8
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/rainy-7.svg
@@ -0,0 +1,91 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/snowy-1.svg b/www/lovelace/custom/weather-card/icons/snowy-1.svg
new file mode 100644
index 0000000..1045466
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/snowy-1.svg
@@ -0,0 +1,230 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/snowy-2.svg b/www/lovelace/custom/weather-card/icons/snowy-2.svg
new file mode 100644
index 0000000..f01f8b7
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/snowy-2.svg
@@ -0,0 +1,237 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/snowy-3.svg b/www/lovelace/custom/weather-card/icons/snowy-3.svg
new file mode 100644
index 0000000..8c51ef8
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/snowy-3.svg
@@ -0,0 +1,268 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/snowy-4.svg b/www/lovelace/custom/weather-card/icons/snowy-4.svg
new file mode 100644
index 0000000..e282d18
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/snowy-4.svg
@@ -0,0 +1,94 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/snowy-5.svg b/www/lovelace/custom/weather-card/icons/snowy-5.svg
new file mode 100644
index 0000000..463d6d8
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/snowy-5.svg
@@ -0,0 +1,166 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/snowy-6.svg b/www/lovelace/custom/weather-card/icons/snowy-6.svg
new file mode 100644
index 0000000..beba9e4
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/snowy-6.svg
@@ -0,0 +1,225 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/thunder.svg b/www/lovelace/custom/weather-card/icons/thunder.svg
new file mode 100644
index 0000000..a27ff55
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/thunder.svg
@@ -0,0 +1,268 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/weather-sprite.svg b/www/lovelace/custom/weather-card/icons/weather-sprite.svg
new file mode 100644
index 0000000..b0117b7
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/weather-sprite.svg
@@ -0,0 +1,1245 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/weather.svg b/www/lovelace/custom/weather-card/icons/weather.svg
new file mode 100644
index 0000000..7258930
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/weather.svg
@@ -0,0 +1,1245 @@
+
+
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/weather_sagittarius.svg b/www/lovelace/custom/weather-card/icons/weather_sagittarius.svg
new file mode 100644
index 0000000..4285ab7
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/weather_sagittarius.svg
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/www/lovelace/custom/weather-card/icons/weather_sunset.svg b/www/lovelace/custom/weather-card/icons/weather_sunset.svg
new file mode 100644
index 0000000..f491da7
--- /dev/null
+++ b/www/lovelace/custom/weather-card/icons/weather_sunset.svg
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/www/lovelace/custom/weather-card/weather-card-editor.js b/www/lovelace/custom/weather-card/weather-card-editor.js
new file mode 100644
index 0000000..1073323
--- /dev/null
+++ b/www/lovelace/custom/weather-card/weather-card-editor.js
@@ -0,0 +1,216 @@
+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;
+};
+
+if (
+ !customElements.get("ha-switch") &&
+ customElements.get("paper-toggle-button")
+) {
+ customElements.define("ha-switch", customElements.get("paper-toggle-button"));
+}
+
+const LitElement = customElements.get("hui-masonry-view") ? Object.getPrototypeOf(customElements.get("hui-masonry-view")) : Object.getPrototypeOf(customElements.get("hui-view"));
+const html = LitElement.prototype.html;
+const css = LitElement.prototype.css;
+
+const HELPERS = window.loadCardHelpers();
+
+export class WeatherCardEditor extends LitElement {
+ setConfig(config) {
+ this._config = { ...config };
+ }
+
+ static get properties() {
+ return { hass: {}, _config: {} };
+ }
+
+ get _entity() {
+ return this._config.entity || "";
+ }
+
+ get _name() {
+ return this._config.name || "";
+ }
+
+ get _icons() {
+ return this._config.icons || "";
+ }
+
+ get _current() {
+ return this._config.current !== false;
+ }
+
+ get _details() {
+ return this._config.details !== false;
+ }
+
+ get _forecast() {
+ return this._config.forecast !== false;
+ }
+
+ get _hourly_forecast() {
+ return this._config.hourly_forecast !== false;
+ }
+
+ get _number_of_forecasts() {
+ return this._config.number_of_forecasts || 5;
+ }
+
+ firstUpdated() {
+ HELPERS.then(help => {
+ if (help.importMoreInfoControl) {
+ help.importMoreInfoControl("fan");
+ }
+ })
+ }
+
+ render() {
+ if (!this.hass) {
+ return html``;
+ }
+
+ const entities = Object.keys(this.hass.states).filter(
+ (eid) => eid.substr(0, eid.indexOf(".")) === "weather"
+ );
+
+ return html`
+
+
+
+
+ ${customElements.get("ha-entity-picker")
+ ? html`
+
+ `
+ : html`
+
+
+ ${entities.map((entity) => {
+ return html` ${entity} `;
+ })}
+
+
+ `}
+
+
+ Show current
+
+
+ Show details
+
+
+ Show forecast
+
+
+ Show hourly forecast
+
+
+
+
+
+ `;
+ }
+
+ _valueChanged(ev) {
+ if (!this._config || !this.hass) {
+ return;
+ }
+ const target = ev.target;
+ if (this[`_${target.configValue}`] === target.value) {
+ return;
+ }
+ if (target.configValue) {
+ if (target.value === "") {
+ delete this._config[target.configValue];
+ } else {
+ this._config = {
+ ...this._config,
+ [target.configValue]:
+ target.checked !== undefined ? target.checked : target.value,
+ };
+ }
+ }
+ fireEvent(this, "config-changed", { config: this._config });
+ }
+
+ static get styles() {
+ return css`
+ .switches {
+ margin: 8px 0;
+ display: flex;
+ justify-content: space-between;
+ }
+ .switch {
+ display: flex;
+ align-items: center;
+ justify-items: center;
+ }
+ .switches span {
+ padding: 0 16px;
+ }
+ `;
+ }
+}
+
+customElements.define("weather-card-editor", WeatherCardEditor);
diff --git a/www/lovelace/custom/weather-card/weather-card.js b/www/lovelace/custom/weather-card/weather-card.js
new file mode 100644
index 0000000..21b41f1
--- /dev/null
+++ b/www/lovelace/custom/weather-card/weather-card.js
@@ -0,0 +1,530 @@
+const LitElement = customElements.get("hui-masonry-view") ? Object.getPrototypeOf(customElements.get("hui-masonry-view")) : Object.getPrototypeOf(customElements.get("hui-view"));
+const html = LitElement.prototype.html;
+const css = LitElement.prototype.css;
+
+const weatherIconsDay = {
+ clear: "day",
+ "clear-night": "night",
+ 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",
+ sunny: "night",
+ partlycloudy: "cloudy-night-3",
+ "windy-variant": "cloudy-night-3",
+};
+
+const windDirections = [
+ "N",
+ "NNE",
+ "NE",
+ "ENE",
+ "E",
+ "ESE",
+ "SE",
+ "SSE",
+ "S",
+ "SSW",
+ "SW",
+ "WSW",
+ "W",
+ "WNW",
+ "NW",
+ "NNW",
+ "N",
+];
+
+window.customCards = window.customCards || [];
+window.customCards.push({
+ type: "weather-card",
+ name: "Weather Card",
+ description: "A custom weather card with animated icons.",
+ preview: true,
+ documentationURL: "https://github.com/bramkragten/weather-card",
+});
+
+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 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("./weather-card-editor.js.js.js");
+ return document.createElement("weather-card-editor");
+ }
+
+ static getStubConfig(hass, unusedEntities, allEntities) {
+ let entity = unusedEntities.find((eid) => eid.split(".")[0] === "weather");
+ if (!entity) {
+ entity = allEntities.find((eid) => eid.split(".")[0] === "weather");
+ }
+ return { entity };
+ }
+
+ 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``;
+ }
+
+ this.numberElements = 0;
+
+ const stateObj = this.hass.states[this._config.entity];
+
+ if (!stateObj) {
+ return html`
+
+
+
+ Entity not available: ${this._config.entity}
+
+
+ `;
+ }
+
+ return html`
+
+ ${this._config.current !== false ? this.renderCurrent(stateObj) : ""}
+ ${this._config.details !== false ? this.renderDetails(stateObj) : ""}
+ ${this._config.forecast !== false
+ ? this.renderForecast(stateObj.attributes.forecast)
+ : ""}
+
+ `;
+ }
+
+ renderCurrent(stateObj) {
+ this.numberElements++;
+
+ return html`
+
+ ${stateObj.state}
+
+ ${this._config.name
+ ? html` ${this._config.name} `
+ : ""}
+ ${this.getUnit("temperature") == "°F"
+ ? Math.round(stateObj.attributes.temperature)
+ : stateObj.attributes.temperature}
+ ${this.getUnit("temperature")}
+
+ `;
+ }
+
+ renderDetails(stateObj) {
+ const sun = this.hass.states["sun.sun"];
+ let next_rising;
+ let next_setting;
+
+ if (sun) {
+ next_rising = new Date(sun.attributes.next_rising);
+ next_setting = new Date(sun.attributes.next_setting);
+ }
+
+ this.numberElements++;
+
+ return html`
+
+ -
+
+ ${stateObj.attributes.humidity} %
+
+ -
+ ${windDirections[
+ parseInt((stateObj.attributes.wind_bearing + 11.25) / 22.5)
+ ]}
+ ${stateObj.attributes.wind_speed}
+ ${this.getUnit("length")}/h
+
+
+ -
+
+ ${stateObj.attributes.pressure}
+
+ ${this.getUnit("air_pressure")}
+
+
+ -
+ ${stateObj.attributes
+ .visibility}
+ ${this.getUnit("length")}
+
+
+ ${next_rising
+ ? html`
+ -
+
+ ${next_rising.toLocaleTimeString()}
+
+ `
+ : ""}
+ ${next_setting
+ ? html`
+ -
+
+ ${next_setting.toLocaleTimeString()}
+
+ `
+ : ""}
+
+ `;
+ }
+
+ renderForecast(forecast) {
+ if (!forecast || forecast.length === 0) {
+ return html``;
+ }
+
+ const lang = this.hass.selectedLanguage || this.hass.language;
+
+ this.numberElements++;
+ return html`
+
+ ${forecast
+ .slice(
+ 0,
+ this._config.number_of_forecasts
+ ? this._config.number_of_forecasts
+ : 5
+ )
+ .map(
+ (daily) => html`
+
+
+ ${this._config.hourly_forecast
+ ? new Date(daily.datetime).toLocaleTimeString(lang, {
+ hour: "2-digit",
+ minute: "2-digit",
+ })
+ : new Date(daily.datetime).toLocaleDateString(lang, {
+ weekday: "short",
+ })}
+
+
+
+ ${daily.temperature}${this.getUnit("temperature")}
+
+ ${daily.templow !== undefined
+ ? html`
+
+ ${daily.templow}${this.getUnit("temperature")}
+
+ `
+ : ""}
+ ${!this._config.hide_precipitation &&
+ daily.precipitation !== undefined &&
+ daily.precipitation !== null
+ ? html`
+
+ ${Math.round(daily.precipitation*10)/10} ${this.getUnit("precipitation")}
+
+ `
+ : ""}
+ ${!this._config.hide_precipitation &&
+ daily.precipitation_probability !== undefined &&
+ daily.precipitation_probability !== null
+ ? html`
+
+ ${Math.round(daily.precipitation_probability)} ${this.getUnit("precipitation_probability")}
+
+ `
+ : ""}
+
+ `
+ )}
+
+ `;
+ }
+
+ getWeatherIcon(condition, sun) {
+ return `${
+ this._config.icons
+ ? this._config.icons
+ : "https://cdn.jsdelivr.net/gh/bramkragten/weather-card/dist/icons/"
+ }${
+ sun && sun.state == "below_horizon"
+ ? weatherIconsNight[condition]
+ : weatherIconsDay[condition]
+ }.svg`;
+ }
+
+ 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";
+ case "precipitation_probability":
+ return "%";
+ default:
+ return this.hass.config.unit_system[measure] || "";
+ }
+ }
+
+ _handleClick() {
+ fireEvent(this, "hass-more-info", { entityId: this._config.entity });
+ }
+
+ getCardSize() {
+ return 3;
+ }
+
+ static get styles() {
+ return css`
+ ha-card {
+ cursor: pointer;
+ margin: auto;
+ overflow: hidden;
+ padding-top: 1.3em;
+ padding-bottom: 1.3em;
+ padding-left: 1em;
+ padding-right: 1em;
+ position: relative;
+ }
+
+ .spacer {
+ padding-top: 1em;
+ }
+
+ .clear {
+ clear: both;
+ }
+
+ .title {
+ position: absolute;
+ left: 3em;
+ font-weight: 300;
+ font-size: 3em;
+ color: var(--primary-text-color);
+ }
+
+ .temp {
+ font-weight: 300;
+ font-size: 4em;
+ color: var(--primary-text-color);
+ position: absolute;
+ right: 1em;
+ }
+
+ .tempc {
+ font-weight: 300;
+ font-size: 1.5em;
+ vertical-align: super;
+ color: var(--primary-text-color);
+ position: absolute;
+ right: 1em;
+ margin-top: -14px;
+ margin-right: 7px;
+ }
+
+ @media (max-width: 460px) {
+ .title {
+ font-size: 2.2em;
+ left: 4em;
+ }
+ .temp {
+ font-size: 3em;
+ }
+ .tempc {
+ font-size: 1em;
+ }
+ }
+
+ .current {
+ padding: 1.2em 0;
+ margin-bottom: 3.5em;
+ }
+
+ .variations {
+ display: flex;
+ flex-flow: row wrap;
+ justify-content: space-between;
+ font-weight: 300;
+ color: var(--primary-text-color);
+ list-style: none;
+ padding: 0 1em;
+ margin: 0;
+ }
+
+ .variations ha-icon {
+ height: 22px;
+ margin-right: 5px;
+ color: var(--paper-item-icon-color);
+ }
+
+ .variations li {
+ flex-basis: auto;
+ width: 50%;
+ }
+
+ .variations li:nth-child(2n) {
+ text-align: right;
+ }
+
+ .variations li:nth-child(2n) ha-icon {
+ margin-right: 0;
+ margin-left: 8px;
+ float: right;
+ }
+
+ .unit {
+ font-size: 0.8em;
+ }
+
+ .forecast {
+ width: 100%;
+ margin: 0 auto;
+ display: flex;
+ }
+
+ .day {
+ flex: 1;
+ display: block;
+ text-align: center;
+ color: var(--primary-text-color);
+ border-right: 0.1em solid #d9d9d9;
+ line-height: 2;
+ box-sizing: border-box;
+ }
+
+ .dayname {
+ text-transform: uppercase;
+ }
+
+ .forecast .day:first-child {
+ margin-left: 0;
+ }
+
+ .forecast .day:nth-last-child(1) {
+ border-right: none;
+ margin-right: 0;
+ }
+
+ .highTemp {
+ font-weight: bold;
+ }
+
+ .lowTemp {
+ color: var(--secondary-text-color);
+ }
+
+ .precipitation {
+ color: var(--primary-text-color);
+ font-weight: 300;
+ }
+
+ .icon.bigger {
+ width: 10em;
+ height: 10em;
+ margin-top: -4em;
+ position: absolute;
+ left: 0em;
+ }
+
+ .icon {
+ width: 50px;
+ height: 50px;
+ margin-right: 5px;
+ display: inline-block;
+ vertical-align: middle;
+ background-size: contain;
+ background-position: center center;
+ background-repeat: no-repeat;
+ text-indent: -9999px;
+ }
+
+ .weather {
+ font-weight: 300;
+ font-size: 1.5em;
+ color: var(--primary-text-color);
+ text-align: left;
+ position: absolute;
+ top: -0.5em;
+ left: 6em;
+ word-wrap: break-word;
+ width: 30%;
+ }
+ `;
+ }
+}
+customElements.define("weather-card", WeatherCard);
diff --git a/www/lovelace/resources/auto-entities.js b/www/lovelace/resources/auto-entities.js
deleted file mode 100644
index 7c37cdb..0000000
--- a/www/lovelace/resources/auto-entities.js
+++ /dev/null
@@ -1,2 +0,0 @@
-!function(t){var e={};function i(r){if(e[r])return e[r].exports;var s=e[r]={i:r,l:!1,exports:{}};return t[r].call(s.exports,s,s.exports,i),s.l=!0,s.exports}i.m=t,i.c=e,i.d=function(t,e,r){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(i.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var s in t)i.d(r,s,function(e){return t[e]}.bind(null,s));return r},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=0)}([function(t,e,i){"use strict";i.r(e);const r=customElements.get("home-assistant-main")?Object.getPrototypeOf(customElements.get("home-assistant-main")):Object.getPrototypeOf(customElements.get("hui-view")),s=r.prototype.html;r.prototype.css;function n(){return document.querySelector("hc-main")?document.querySelector("hc-main").hass:document.querySelector("home-assistant")?document.querySelector("home-assistant").hass:void 0}const a=n().callWS({type:"config/area_registry/list"}),o=n().callWS({type:"config/device_registry/list"}),c=n().callWS({type:"config/entity_registry/list"});async function l(){return window.cardToolsData=window.cardToolsData||{areas:await a,devices:await o,entities:await c},window.cardToolsData}function u(t){const e=window.cardToolsData;let i=[];if(!t)return i;for(const r of e.devices)r.area_id===t.area_id&&i.push(r);return i}function f(t){const e=window.cardToolsData;let i=[];if(!t)return i;for(const r of e.entities)r.device_id===t.id&&i.push(r.entity_id);return i}function d(t,e){if("string"==typeof e&&"string"==typeof t&&(t.startsWith("/")&&t.endsWith("/")||-1!==t.indexOf("*"))){return t.startsWith("/")||(t=`/^${t=t.replace(/\./g,".").replace(/\*/g,".*")}$/`),new RegExp(t.slice(1,-1)).test(e)}if("string"==typeof t){if(t.startsWith("<="))return parseFloat(e)<=parseFloat(t.substr(2));if(t.startsWith(">="))return parseFloat(e)>=parseFloat(t.substr(2));if(t.startsWith("<"))return parseFloat(e)
"))return parseFloat(e)>parseFloat(t.substr(1));if(t.startsWith("!"))return parseFloat(e)!=parseFloat(t.substr(1));if(t.startsWith("="))return parseFloat(e)==parseFloat(t.substr(1))}return t===e}function h(t,e){return function(i){const r="string"==typeof i?t.states[i]:t.states[i.entity];if(!i)return!1;for(const[s,n]of Object.entries(e))switch(s.split(" ")[0]){case"options":case"sort":break;case"domain":if(!d(n,r.entity_id.split(".")[0]))return!1;break;case"entity_id":if(!d(n,r.entity_id))return!1;break;case"state":if(!d(n,r.state))return!1;break;case"name":if(!r.attributes.friendly_name||!d(n,r.attributes.friendly_name))return!1;break;case"group":if(!(n.startsWith("group.")&&t.states[n]&&t.states[n].attributes.entity_id&&t.states[n].attributes.entity_id.includes(r.entity_id)))return!1;break;case"attributes":for(const[t,e]of Object.entries(n)){let i=t.trim(),s=r.attributes;for(;i&&s;){let t;[t,i]=i.split(":"),s=s[t]}if(void 0===s||void 0!==e&&!d(e,s))return!1}break;case"not":if(h(t,n)(i))return!1;break;case"device":if(!window.cardToolsData||!window.cardToolsData.devices)return!1;let e=!1;for(const t of window.cardToolsData.devices)d(n,t.name)&&f(t).includes(r.entity_id)&&(e=!0);if(!e)return!1;break;case"area":if(!window.cardToolsData||!window.cardToolsData.areas)return!1;let s=!1;for(const t of window.cardToolsData.areas)d(n,t.name)&&u(t).flatMap(f).includes(r.entity_id)&&(s=!0);if(!s)return!1;break;case"last_changed":if(!d(n,((new Date).getTime()-new Date(r.last_changed).getTime())/6e4))return!1;break;case"last_updated":if(!d(n,((new Date).getTime()-new Date(r.last_updated).getTime())/6e4))return!1;break;default:return!1}return!0}}function g(t,e){return"string"==typeof e&&(e={method:e}),function(i,r){const s="string"==typeof i?t.states[i]:t.states[i.entity],n="string"==typeof r?t.states[r]:t.states[r.entity];if(void 0===s||void 0===n)return 0;const[a,o]=e.reverse?[-1,1]:[1,-1];function c(t,i){return e.ignore_case&&t.toLowerCase&&(t=t.toLowerCase()),e.ignore_case&&i.toLowerCase&&(i=i.toLowerCase()),e.numeric&&(isNaN(parseFloat(t))&&isNaN(parseFloat(i))||(t=isNaN(parseFloat(t))?void 0:parseFloat(t),i=isNaN(parseFloat(i))?void 0:parseFloat(i))),void 0===t&&void 0===i?0:void 0===t?a:void 0===i?o:ti?a:0}switch(e.method){case"domain":return c(s.entity_id.split(".")[0],n.entity_id.split(".")[0]);case"entity_id":return c(s.entity_id,n.entity_id);case"friendly_name":case"name":return c(s.attributes.friendly_name||s.entity_id.split(".")[1],n.attributes.friendly_name||n.entity_id.split(".")[1]);case"state":return c(s.state,n.state);case"attribute":let t=s.attributes,i=n.attributes,r=e.attribute;for(;r;){let e;if([e,r]=r.split(":"),t=t[e],i=i[e],void 0===t&&void 0===i)return 0;if(void 0===t)return a;if(void 0===i)return o}return c(t,i);case"last_changed":case"last_updated":return e.numeric=!0,c(new Date(n.last_changed).getTime(),new Date(s.last_changed).getTime());case"last_triggered":return null==s.attributes.last_triggered||null==n.attributes.last_triggered?0:(e.numeric=!0,c(new Date(n.attributes.last_triggered).getTime(),new Date(s.attributes.last_triggered).getTime()));default:return 0}}}function p(t,e,i=null){if((t=new Event(t,{bubbles:!0,cancelable:!1,composed:!0})).detail=e||{},i)i.dispatchEvent(t);else{var r=function(){var t=document.querySelector("hc-main");return t=t?(t=(t=(t=t&&t.shadowRoot)&&t.querySelector("hc-lovelace"))&&t.shadowRoot)&&t.querySelector("hui-view"):(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=document.querySelector("home-assistant"))&&t.shadowRoot)&&t.querySelector("home-assistant-main"))&&t.shadowRoot)&&t.querySelector("app-drawer-layout partial-panel-resolver"))&&t.shadowRoot||t)&&t.querySelector("ha-panel-lovelace"))&&t.shadowRoot)&&t.querySelector("hui-root"))&&t.shadowRoot)&&t.querySelector("ha-app-layout #view"))&&t.firstElementChild}();r&&r.dispatchEvent(t)}}l();function y(t,e){const i=document.createElement("hui-error-card");return i.setConfig({type:"error",error:t,origConfig:e}),i}function m(t,e){if(!e||"object"!=typeof e||!e.type)return y(`No ${t} type configured`,e);let i=e.type;if(i=i.startsWith("custom:")?i.substr("custom:".length):`hui-${i}-${t}`,customElements.get(i))return function(t,e){const i=document.createElement(t);try{i.setConfig(e)}catch(t){return y(t,e)}return i}(i,e);const r=y(`Custom element doesn't exist: ${i}.`,e);r.style.display="None";const s=setTimeout(()=>{r.style.display=""},2e3);return customElements.whenDefined(i).then(()=>{clearTimeout(s),p("ll-rebuild",{},r)}),r}let _=function(){if(window.fully&&"function"==typeof fully.getDeviceId)return fully.getDeviceId();if(!localStorage["lovelace-player-device-id"]){const t=()=>Math.floor(1e5*(1+Math.random())).toString(16).substring(1);localStorage["lovelace-player-device-id"]=`${t()}${t()}-${t()}${t()}`}return localStorage["lovelace-player-device-id"]}();customElements.define("auto-entities",class extends r{static get properties(){return{hass:{}}}setConfig(t){if(!t||!t.card)throw new Error("Invalid configuration");this._config?(this._config=t,this.hass=this.hass):(this._config=t,this.hass=n(),this._getEntities(),this.cardConfig={entities:this.entities,...t.card},this.card=function(t){return m("card",t)}(this.cardConfig)),t.filter&&t.filter.template&&(this.template="",(String(t.filter.template).includes("{%")||String(t.filter.template).includes("{{"))&&function(t,e,i){t||(t=n().connection);let r={user:n().user.name,browser:_,hash:location.hash.substr(1)||" ",...i.variables},s=i.template,a=i.entity_ids;t.subscribeMessage(t=>{let i=t.result;i=i.replace(/_\([^)]*\)/g,t=>n().localize(t.substring(2,t.length-1))||t),e(i)},{type:"render_template",template:s,variables:r,entity_ids:a})}(null,t=>{this.template=t,this._getEntities()},{template:t.filter.template,variables:{config:t},entity_ids:t.filter.entity_ids})),l().then(()=>this._getEntities())}_getEntities(){const t=t=>t?"string"==typeof t?{entity:t.trim()}:t:null;let e=[];if(this._config.entities&&(e=e.concat(this._config.entities.map(t))),!this.hass||!this._config.filter)return e;if(this.template&&(e=e.concat(this.template.split(/[\s,]+/).map(t))),e=e.filter(Boolean),this._config.filter.include){const i=Object.keys(this.hass.states).map(t);for(const t of this._config.filter.include){if(void 0!==t.type){e.push(t);continue}let r=i.filter(h(this.hass,t)).map(e=>JSON.parse(JSON.stringify(new Object({...e,...t.options})).replace(/this.entity_id/g,e.entity)));void 0!==t.sort&&(r=r.sort(g(this.hass,t.sort))),e=e.concat(r)}}if(this._config.filter.exclude)for(const t of this._config.filter.exclude)e=e.filter(e=>"string"!=typeof e&&void 0===e.entity||!h(this.hass,t)(e));if(this._config.sort&&(e=e.sort(g(this.hass,this._config.sort)),this._config.sort.count)){const t=this._config.sort.first||0;e=e.slice(t,t+this._config.sort.count)}if(this._config.unique){function i(t,e){return typeof t==typeof e&&("object"!=typeof t?t===e:!Object.keys(t).some(t=>!Object.keys(e).includes(t))&&Object.keys(t).every(r=>i(t[r],e[r])))}let t=[];for(const r of e)t.some(t=>i(t,r))||t.push(r);e=t}this.entities=e}set entities(t){(function(t,e){if(t===e)return!0;if(null==t||null==e)return!1;if(t.length!=e.length)return!1;for(var i=0;ithis._getEntities(),0))}createRenderRoot(){return this}render(){return s`
- ${this.card}`}getCardSize(){let t=0;return this.card&&this.card.getCardSize&&(t=this.card.getCardSize()),1===t&&this.entities.length&&(t=this.entities.length),0===t&&this._config.filter&&this._config.filter.include&&(t=Object.keys(this._config.filter.include).length),t||1}}),p("ll-rebuild",{})}]);
\ No newline at end of file
diff --git a/www/lovelace/resources/color-lite-card.js b/www/lovelace/resources/color-lite-card.js
deleted file mode 100644
index 357a293..0000000
--- a/www/lovelace/resources/color-lite-card.js
+++ /dev/null
@@ -1,64 +0,0 @@
-class ColorLite extends HTMLElement {
- set hass(hass) {
- if (!this.content) {
- const card = document.createElement('ha-card');
- this.content = document.createElement('div');
- card.appendChild(this.content);
- card.style.background = 'none';
- this.appendChild(card);
- }
-
- const entityId = this.config.entity;
- const state = hass.states[entityId];
-
-
- // if the light is on
- if(state){
- if(state.state == 'on'){
-
- const imageURLId = this.config.image;
- var ImURL = imageURLId;
- const imageURLCId = this.config.color_image;
- var rgbval = state.attributes.rgb_color;
- var hsval = state.attributes.hs_color;
- var hsar = "";
- if (hsval) {
- if (rgbval != "255,255,255") {
- var hsar = ' hue-rotate(' + hsval[0] + 'deg)';
- if (imageURLCId) {
- ImURL = imageURLCId;
- }
- }
- }
- var bbritef = state.attributes.brightness;
- var bbrite = (bbritef / 205);
-
- this.content.innerHTML = `
-
-
- `;
-
- } else {
- this.content.innerHTML = `
-
- `;
- }
- }
- }
-
-
- setConfig(config) {
- if (!config.entity) {
- throw new Error('You need to define an entity');
- }
- this.config = config;
- }
-
- // The height of your card. Home Assistant uses this to automatically
- // distribute all cards over the available columns.
- getCardSize() {
- return 3;
- }
- }
-
- customElements.define('color-lite-card', ColorLite);
\ No newline at end of file
diff --git a/www/lovelace/resources/now-playing-card.js b/www/lovelace/resources/now-playing-card.js
deleted file mode 100644
index 4f92c3c..0000000
--- a/www/lovelace/resources/now-playing-card.js
+++ /dev/null
@@ -1,102 +0,0 @@
-class NowPlayingPoster extends HTMLElement {
- set hass(hass) {
- if (!this.content) {
- const card = document.createElement('ha-card');
- this.content = document.createElement('div');
-
-
- //this.content.style = "!important;";
-
-
- card.appendChild(this.content);
- card.style = "background: none;";
- this.appendChild(card);
-
-
- }
-
- const offposter = this.config.off_image;
- const entityId = this.config.entity;
- const state = hass.states[entityId];
- const stateStr = state ? state.state : 'unavailable';
-
-
-
- if (state) {
-
- const movposter = state.attributes.entity_picture;
-
- if (stateStr == "playing") {
- if ( !movposter ) {
- if ( offposter ) {
- this.content.innerHTML = `
-
-
- `;
- }
- else
- {
- this.content.innerHTML = `
-
- `;
- }
- }
- else
- {
- this.content.innerHTML = `
-
-
- `;
- }
- }
- else
- {
-
- if ( offposter ) {
- this.content.innerHTML = `
-
-
- `;
- }
- else
- {
- this.content.innerHTML = `
-
- `;
- }
-
- }
-
-
- }
- else
- {
-
-
- this.content.innerHTML = `
-
- `;
-
- }
-
- }
-
-
-
-
- setConfig(config) {
- if (!config.entity) {
- throw new Error('You need to define an entity');
- }
- this.config = config;
- }
-
-
- // The height of your card. Home Assistant uses this to automatically
- // distribute all cards over the available columns.
- getCardSize() {
- return 3;
- }
- }
-
- customElements.define('now-playing-poster', NowPlayingPoster);
\ No newline at end of file
diff --git a/www/lovelace/resources/weather-card.js b/www/lovelace/resources/weather-card.js
deleted file mode 100644
index 215cf8d..0000000
--- a/www/lovelace/resources/weather-card.js
+++ /dev/null
@@ -1,247 +0,0 @@
-/**
- * Minified by jsDelivr using Terser v3.14.1.
- * Original file: /gh/bramkragten/custom-ui@null/weather-card/weather-card.js
- *
- * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
- */
-const LitElement=Object.getPrototypeOf(customElements.get("ha-panel-lovelace")),html=LitElement.prototype.html,weatherIconsDay={clear:"day","clear-night":"night",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:"!!"},weatherIconsNight={...weatherIconsDay,clear:"night",sunny:"night",partlycloudy:"cloudy-night-3","windy-variant":"cloudy-night-3"},windDirections=["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW","N"],fireEvent=(t,e,i,n)=>{n=n||{},i=null==i?{}:i;const a=new Event(e,{bubbles:void 0===n.bubbles||n.bubbles,cancelable:Boolean(n.cancelable),composed:void 0===n.composed||n.composed});return a.detail=i,t.dispatchEvent(a),a};function hasConfigOrEntityChanged(t,e){if(e.has("_config"))return!0;const i=e.get("hass");return!i||(i.states[t._config.entity]!==t.hass.states[t._config.entity]||i.states["sun.sun"]!==t.hass.states["sun.sun"])}class WeatherCard extends LitElement{static get properties(){return{_config:{},hass:{}}}static async getConfigElement(){return await import("./weather-card-editor.js"),document.createElement("weather-card-editor")}static getStubConfig(){return{}}setConfig(t){if(!t.entity)throw new Error("Please define a weather entity");this._config=t}shouldUpdate(t){return hasConfigOrEntityChanged(this,t)}render(){if(!this._config||!this.hass)return html``;const t=this.hass.states[this._config.entity];if(!t)return html`
-
-
-
- Entity not available: ${this._config.entity}
-
-
- `;const e=this.hass.selectedLanguage||this.hass.language,i=new Date(this.hass.states["sun.sun"].attributes.next_rising),n=new Date(this.hass.states["sun.sun"].attributes.next_setting);return html`
- ${this.renderStyle()}
-
- ${t.state}
-
- ${this._config.name?html`
- ${this._config.name}
- `:""}
- ${"°F"==this.getUnit("temperature")?Math.round(t.attributes.temperature):t.attributes.temperature}
- ${this.getUnit("temperature")}
-
-
- -
-
- ${t.attributes.humidity} %
-
-
- ${windDirections[parseInt((t.attributes.wind_bearing+11.25)/22.5)]}
- ${t.attributes.wind_speed}
- ${this.getUnit("length")}/h
-
-
-
- ${i.toLocaleTimeString()}
-
- -
- ${t.attributes.pressure}
- ${this.getUnit("air_pressure")}
-
-
-
- ${t.attributes.visibility}
- ${this.getUnit("length")}
-
-
-
- ${n.toLocaleTimeString()}
-
-
-
- ${t.attributes.forecast&&t.attributes.forecast.length>0?html`
-
- ${t.attributes.forecast.slice(0,5).map(t=>html`
-
- ${new Date(t.datetime).toLocaleDateString(e,{weekday:"short"})}
-
-
${t.temperature}${this.getUnit("temperature")}
- ${void 0!==t.templow?html`
-
${t.templow}${this.getUnit("temperature")}
- `:""}
-
- `)}
-
- `:""}
-
- `}getWeatherIcon(t,e){return`${this._config.icons?this._config.icons:"https://cdn.jsdelivr.net/gh/bramkragten/custom-ui@master/weather-card/icons/animated/"}${e&&"below_horizon"==e?weatherIconsNight[t]:weatherIconsDay[t]}.svg`}getUnit(t){const e=this.hass.config.unit_system.length;switch(t){case"air_pressure":return"km"===e?"hPa":"inHg";case"length":return e;case"precipitation":return"km"===e?"mm":"in";default:return this.hass.config.unit_system[t]||""}}_handleClick(){fireEvent(this,"hass-more-info",{entityId:this._config.entity})}getCardSize(){return 3}renderStyle(){return html`
-
- `}}customElements.define("weather-card",WeatherCard);
\ No newline at end of file
diff --git a/www/vacuums/Dobby_liveMap.png b/www/vacuums/Dobby_liveMap.png
new file mode 100644
index 0000000..bbf50e1
Binary files /dev/null and b/www/vacuums/Dobby_liveMap.png differ