├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── changelog.md ├── home-card-editor.js ├── home-card.js ├── images ├── card-editor.png ├── demo.gif ├── ranch_home.png └── structure.png ├── themes.js └── themes ├── ranch_with_three_stall_garage ├── car.png ├── door-close.png ├── door-open.png ├── garage-close.png ├── garage-open.png ├── house.png ├── outside-light-off.png ├── outside-light-on.png ├── sprinkler-off.png ├── sprinkler-on.png ├── utility-electricity.png ├── utility-water.png ├── weather-cloudy.png ├── weather-exceptional.png ├── weather-fog.png ├── weather-hail.png ├── weather-lightning-rainy.png ├── weather-lightning.png ├── weather-partlycloudy.png ├── weather-pouring.png ├── weather-rainy.png ├── weather-snowy-rainy.png ├── weather-snowy.png ├── weather-sun.png ├── weather-sunny.png ├── weather-windy-variant.png ├── weather-windy.png ├── window-dark.png └── window-light.png └── two_story_with_garage ├── car.png ├── door-close.png ├── door-open.png ├── garage-close.png ├── garage-open.png ├── house.png ├── outside-light-off.png ├── outside-light-on.png ├── sprinkler-off.png ├── sprinkler-on.png ├── utility-electricity.png ├── utility-water.png ├── weather-cloudy.png ├── weather-exceptional.png ├── weather-fog.png ├── weather-hail.png ├── weather-lightning-rainy.png ├── weather-lightning.png ├── weather-partlycloudy.png ├── weather-pouring.png ├── weather-rainy.png ├── weather-snowy-rainy.png ├── weather-snowy.png ├── weather-sun.png ├── weather-sunny.png ├── weather-windy-variant.png ├── weather-windy.png ├── window-dark.png └── window-light.png /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [postlund] 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Pierre Ståhl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Home Card 2 | 3 | A quick glance of the state of your home in [Home Assistant](https://github.com/home-assistant/home-assistant) Lovelace UI. 4 | 5 | ![Demo of card](images/demo.gif) 6 | 7 | Initial work on UI editor (only some options can be edited): 8 | 9 | ![UI Editor](images/card-editor.png) 10 | 11 | *Note: This card is still in early development (preview/proof-of-concept), beware of bugs and lacking features!* 12 | 13 | ## Features 14 | 15 | * Graphical representation of your home with different themes 16 | * Displays things such as weather, state of lights and garage door as well as arbitrary sensors 17 | * Lovelace UI editor for some options (still early work) 18 | * Flexible tap and hold actions (same as for entity-button) 19 | * Create your own custom themes! 20 | * Transparent or regular paper card background 21 | 22 | ## Roadmap 23 | 24 | Some things I want to add in upcoming releases: 25 | 26 | * More house types and better graphics 27 | * Extend with additional overlays for things like alarm, people and doors 28 | * More ways to customize how the card looks and feel 29 | * Extend or override existing themes using `custom_themes` 30 | * More improved Lovelace UI editor 31 | * Support for custom_updater 32 | * Better development environment with linting, etc. 33 | 34 | ## Install 35 | 36 | ### Simple Install 37 | 38 | 1. Download `home-card.js`, `themes.js` and `themes` and copy them into `config/www/home-card` (create the `home-card` directory) 39 | 40 | 2. Add a reference to `home-card/home-card.js` inside your `ui-lovelace.yaml` 41 | 42 | ```yaml 43 | resources: 44 | - url: /local/home-card/home-card.js?v=0 45 | type: module 46 | ``` 47 | 48 | ### Git Install 49 | 50 | 1. Clone this repository into your `www`-directory: `git clone https://github.com/postlund/home-card.git` 51 | 52 | 2. Add a reference to `home-card/home-card.js` inside your `ui-lovelace.yaml` 53 | 54 | ```yaml 55 | resources: 56 | - url: /local/home-card/home-card.js?v=0 57 | type: module 58 | ``` 59 | 60 | ### Custom updater 61 | 62 | Not using this yet... 63 | 64 | ## Updating 65 | 66 | If you... 67 | 68 | * manually copied the files, just download the latest files and overwrite what you already have 69 | * cloned the repository from Github, just do `git pull` to update 70 | 71 | ... and increase `?v=X` to `?vX+1`. 72 | 73 | ## Using the card 74 | 75 | ### Card layout 76 | 77 | The card is split into three different areas: 78 | 79 | ![Structure of card](/images/structure.png) 80 | 81 | Explanation of each area: 82 | 83 | * Weather area (Red): Displays current weather with an icon (e.g. sun or cloud) and temperature. Name of location is displayed as well. Controlled by the `weather` option. 84 | * House area (Green): Main visualization of the house. Consists of `overlay` images that can be shown or hidden depending on an entity state. A car overlay (image) can for instance be shown if `device_tracker.car` has the state `home`. Controlled by the `entities` option. 85 | * Resources (Blue): Simplistic view of sensors. Controlled by the `resources` option. 86 | 87 | Both the weather and resources areas are optional and will not displayed if omitted from the configuration. The house area are however mandatory. 88 | 89 | ### Options 90 | 91 | | Name | Type | Default | Description | 92 | |------|------|---------|-------------| 93 | | type | string | **required** | `custom:home-card` 94 | | theme | string | **required** | Name of a theme, see [supported themes](#supported-themes) 95 | | background | string | transparent | Supported values: empty, `transparent`, `paper-card` 96 | | weather | string | optional | `weather` entity used for displaying location and temperature 97 | | entities | object | optional | List of [entity objects](#entity-object) 98 | | resources | object | optional | List of [resource objects](#resource-object) 99 | | custom_themes | object | optional | List of [theme objects](#theme-object) 100 | 101 | #### Supported themes 102 | 103 | The following themes and overlays are currently supported: 104 | 105 | | Theme | Overlays | 106 | |------|----------| 107 | | two_story_with_garage | door, garage, outside_light, upstairs_light, downstairs_light, car, sprinkler 108 | 109 | These states are supported by the overlays: 110 | 111 | | Overlay | States | Component examples | 112 | |---------|--------|-----------------------| 113 | | car | home, not_home | device_tracker 114 | | door | on, off | E.g. binary_sensor, switch 115 | | downstairs_lights | on, off | E.g. light, binary_sensor 116 | | garage | open, closed | cover 117 | | outside_light | on, off | E.g. light, binary_sensor 118 | | upstairs_lights | on, off | E.g. light, binary_sensor 119 | | sprinkler | on, off | E.g. binary_sensor, switch 120 | 121 | You may add additional state mappings using a `state_map` to support other component types, see [Entity object](#entity-object). 122 | 123 | #### Entity object 124 | 125 | An `entity object` maps an entity in Home Assistant to an overlay in the card, e.g. which `device_tracker` entity that shows/hides the car or which `light` that corresponds to "upstairs". 126 | 127 | | Name | Type | Default | Description | 128 | |------|------|---------|-------------| 129 | | type | string | **required** | Overlay type, see [overlay tabe](#supported-themes) 130 | | entity | string | **required** | Entity id from Home Assistant, e.g. `light.downstairs` 131 | | state_map | map | optional | Key-value map of state (in Home Assistant) to overlay state 132 | 133 | A simple example of an entity object in yaml looks like this: 134 | 135 | ```yaml 136 | - type: car 137 | entity: binary_sensor_.car 138 | state_map: 139 | on: home 140 | off: not_home 141 | ``` 142 | 143 | This object supports custom [tap and hold actions](#tap-and-hold-actions). 144 | 145 | #### Resource object 146 | 147 | A `resource` is a simple sensor that is displayed beneath the house, e.g. a temperature sensor or water usage. You can use any entity but you might have to manually specify an `icon` and/or `unit_of_measurement`. 148 | 149 | | Name | Type | Default | Description | 150 | |------|------|---------|-------------| 151 | | entity | string | **required** | An entity from Home Assistant, e.g, `sensor.water_usage` 152 | | icon | string | optional | Override icon to use, e.g. `mdi:car` 153 | | unit_of_measurement | string | optional | Override unit of measurement, e.g. `lux` 154 | 155 | A simple example of a resource object in yaml looks like this: 156 | 157 | ```yaml 158 | - entity: sensor.water_usage 159 | icon: mdi:water 160 | unit_of_measurement: liter 161 | ``` 162 | 163 | This object supports custom [tap and hold actions](#tap-and-hold-actions). 164 | 165 | #### Theme object 166 | 167 | **THIS IS EXPERIMENTAL AND MAY BREAK LATER - BEWARE!** 168 | 169 | You can define your own themes and use your own images if you like. Some things to consider: 170 | 171 | * Keep images small (in size) to keep everything snappy 172 | * Re-use overlays and names as much as possible to keep themes consistent 173 | * If you make a cool looking theme, feel free to send a PR (make sure to clarify where images come from to cope with licenses) and remember to include a screenshot 174 | * It is currently not possible to alter/extend existing themes, only define additional themes 175 | 176 | The format of this object will be described in more detail once the format has been set, but have a look at the [example](#creating-custom-themes) to see how you configure your theme in current state. 177 | 178 | ### Tap and hold actions 179 | 180 | This card supports custom `tap` and `hold` actions for most things available in the card. Each theme defines the default behavior for how `tap` and `hold` works, but you may freely override this behavior. The exact same format as used by the `entity button` in lovelace is used here. 181 | 182 | The following options are valid for `tap_action` and `hold_action`: 183 | 184 | | Name | Type | Default | Description | 185 | |------|------|---------|-------------| 186 | | action | string | **required** | Action to perform, one of: `more-info`, `toggle`, `call-service`, `navigate`, `none` 187 | | navigation_path | string | optional | Where to navigate (e.g. `/lovelace/1`) when `action` is `navigate` 188 | | service | string | optional | Service to call (e.g. `switch.turn_on`) when `action` is `call-service` 189 | | service_data | string | optional | Service data to include when calling a service (e.g. `entity_id: switch.bedroom`). 190 | 191 | To see an example, click [here](#using-custom-tap-and-hold-actions). 192 | 193 | ### Example usage 194 | 195 | #### Defining a home 196 | 197 | Simple example using basic features: 198 | 199 | ```yaml 200 | - type: 'custom:home-card' 201 | theme: two_story_with_garage 202 | weather: weather.home 203 | entities: 204 | - type: garage 205 | entity: cover.garage_door 206 | - type: upstairs_light 207 | entity: light.demo_upstairs_light 208 | - type: downstairs_light 209 | entity: light_downstairs_light 210 | - type: car 211 | entity: device_tracker.car 212 | resources: 213 | - entity: utility meter.water 214 | - entity: utility meter.electricity 215 | - entity: binary_sensor.movement_backyard 216 | icon: 'mdi:alarm-light' 217 | - entity: sensor.outside_temperature 218 | icon: 'mdi:thermometer' 219 | ``` 220 | 221 | #### Using custom tap and hold actions 222 | 223 | Simple example using various `tap` and `hold` actions: 224 | 225 | ```yaml 226 | - type: 'custom:home-card' 227 | theme: two_story_with_garage 228 | entities: 229 | - type: car 230 | entity: device_tracker.car 231 | tap_action: 232 | action: navigate 233 | navigation_path: /lovelace/2 234 | hold_action: 235 | action: more-info 236 | resources: 237 | - entity: sensor.outside_temperature 238 | tap_action: 239 | action: call-service 240 | service: switch.turn_on 241 | service_data: 242 | entity_id: switch.fan 243 | hold_action: 244 | action: none 245 | ``` 246 | 247 | #### Re-mapping states 248 | 249 | Here, the `car` type is used as an example. It requires the specified entity to be a `device_tracker` as it maps states like `home` and `not_home` to different overlays. But you can add additional mappings to support for instance a `binary_sensor` as well using `state_map`, like below: 250 | 251 | ```yaml 252 | - type: 'custom:home-card' 253 | theme: two_story_with_garage 254 | entities: 255 | - type: car 256 | entity: binary_sensor.car 257 | state_map: 258 | on: home 259 | off: not_home 260 | ``` 261 | 262 | #### Creating custom themes 263 | 264 | You can define you own themes quite simply using `custom_themes`. The basic structure looks like below (`car` is used to illustrate, you may add as many overlays as you like): 265 | 266 | ```yaml 267 | - type: 'custom:home-card' 268 | theme: my_home 269 | entities: 270 | - type: car 271 | entity: device_tracker.car 272 | custom_themes: 273 | my_home: 274 | house: house.png 275 | overlay_actions: 276 | '*': 277 | tap_action: 278 | action: toggle 279 | car: 280 | tap_action: 281 | action: more-info 282 | overlays: 283 | car: 284 | home: 285 | - image: car_home.png 286 | style: 287 | left: 10% 288 | top: 10% 289 | not_home: 290 | - image: car_away.png 291 | style: 292 | left: 40% 293 | top: 40% 294 | ``` 295 | 296 | Some notes here: 297 | 298 | * You can defined multiple images for each state if you like (as a list is used) 299 | * `style` translates to CSS style attributes, so you may use any CSS attributes here 300 | * The theme is called `my_home`, so a directory with the same name must be created in the `themes` directory and all images placed there 301 | * The `house` option is the main backdrop image and must be defined 302 | * Overlay name (e.g. `car`) corresponds to `type` you specify under `entities` and may be anything you like (but try to be consistent with other themes to simply for other users in case you share your theme) 303 | * If an entity in Home Assistant has a state that is not defined by its corresponding overlay, no overlay will be shown 304 | * Different `tap_action` and `hold_action` configurations can be defined for specific overlay taps (like for 'car' in the example) or for all overlays using `*`. 305 | 306 | ## Issues and imitations 307 | 308 | * Very limited lovelace editor support 309 | * Only one theme built-in 310 | 311 | ## Getting errors? 312 | 313 | Clear the browser cache, restart Home Assistant and make sure the configuration is correct. 314 | 315 | If you believe you have found an error, please write an issue. 316 | 317 | ## External resources 318 | 319 | 320 | ### Images 321 | 322 | This card uses some great free resources from Freepik, namely these: 323 | 324 | * [Weather Icons](https://www.freepik.com/free-vector/weather-icons-collection_972339.htm) 325 | * [House](https://www.freepik.com/free-vector/residential-houses-collection-flat-style_2065378.htm) 326 | * [Car](https://www.freepik.com/free-vector/flat-car-different-views_1504979.htm) 327 | 328 | ### Other resources 329 | 330 | The excellent `clear` theme is used in demo graphics, you can find it here: 331 | 332 | https://community.home-assistant.io/t/clear-theme/100464 333 | 334 | Background image is linked from the same page as well. -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | ## v0.1 2 | 3 | - Initial version 4 | -------------------------------------------------------------------------------- /home-card-editor.js: -------------------------------------------------------------------------------- 1 | import { THEMES } from './themes.js'; 2 | 3 | // Not sure this is really needed, should be available through the frontend? 4 | const deps = ['paper-input', 'paper-dropdown-menu', 'paper-item', 'paper-listbox']; 5 | deps.map(dep => { 6 | if (!customElements.get(dep)) { 7 | console.log("imported", dep); 8 | import(`https://unpkg.com/@polymer/${dep}/${dep}.js?module`); 9 | } 10 | }); 11 | 12 | const fireEvent = (node, type, detail, options) => { 13 | options = options || {}; 14 | detail = detail === null || detail === undefined ? {} : detail; 15 | const event = new Event(type, { 16 | bubbles: options.bubbles === undefined ? true : options.bubbles, 17 | cancelable: Boolean(options.cancelable), 18 | composed: options.composed === undefined ? true : options.composed 19 | }); 20 | event.detail = detail; 21 | node.dispatchEvent(event); 22 | return event; 23 | }; 24 | 25 | const LitElement = Object.getPrototypeOf( 26 | customElements.get("ha-panel-lovelace") 27 | ); 28 | const html = LitElement.prototype.html; 29 | 30 | export class HomeCardEditor extends LitElement { 31 | setConfig(config) { 32 | this.config = config; 33 | } 34 | 35 | static get properties() { 36 | return { 37 | hass: {}, 38 | config: {} 39 | }; 40 | } 41 | 42 | get _weather() { 43 | return this.config.weather || ""; 44 | } 45 | 46 | render() { 47 | if (!this.hass) { 48 | return html``; 49 | } 50 | return html` 51 |
52 | ${this.make_dropdown("Theme", "theme", Object.keys(Object.assign({}, THEMES, this.config.custom_themes)))} 53 | ${this.make_dropdown("Background", "background", ["transparent", "paper-card"])} 54 | 60 |
61 | `; 62 | } 63 | 64 | make_dropdown(label, configValue, items) { 65 | var selected = Math.max(0, items.indexOf(this.config[configValue])); 66 | return html` 67 |
68 | 72 | 73 | ${items.map( 74 | (name) => html` 75 | ${name} 76 | ` 77 | )} 78 | 79 | 80 |
81 | `; 82 | } 83 | 84 | _valueChanged(ev) { 85 | if (!this.config || !this.hass) { 86 | return; 87 | } 88 | const target = ev.target; 89 | if (this[`_${target.configValue}`] === target.value) { 90 | return; 91 | } 92 | if (target.configValue) { 93 | if (target.value === "") { 94 | delete this.config[target.configValue]; 95 | } else { 96 | this.config = { 97 | ...this.config, 98 | [target.configValue]: target.value 99 | }; 100 | } 101 | } 102 | fireEvent(this, "config-changed", { config: this.config }); 103 | } 104 | } 105 | 106 | customElements.define("home-card-editor", HomeCardEditor); -------------------------------------------------------------------------------- /home-card.js: -------------------------------------------------------------------------------- 1 | import { THEMES } from './themes.js'; 2 | 3 | import { 4 | LitElement, 5 | html, 6 | css, 7 | } from 'https://unpkg.com/lit-element@2.0.1/lit-element.js?module'; 8 | 9 | const VERSION = 4; 10 | 11 | // From weather-card 12 | const fireEvent = (node, type, detail, options) => { 13 | options = options || {}; 14 | detail = detail === null || detail === undefined ? {} : detail; 15 | const event = new Event(type, { 16 | bubbles: options.bubbles === undefined ? true : options.bubbles, 17 | cancelable: Boolean(options.cancelable), 18 | composed: options.composed === undefined ? true : options.composed 19 | }); 20 | event.detail = detail; 21 | node.dispatchEvent(event); 22 | return event; 23 | }; 24 | 25 | class HomeCard extends LitElement { 26 | 27 | static get properties() { 28 | return { 29 | config: {}, 30 | hass: {}, 31 | held: false, 32 | timer: {}, 33 | }; 34 | } 35 | 36 | static async getConfigElement() { 37 | await import("./home-card-editor.js"); 38 | return document.createElement("home-card-editor"); 39 | } 40 | 41 | static getStubConfig() { 42 | return { 43 | tap_action: { action: "more-info" }, 44 | hold_action: { action: "none" }, 45 | }; 46 | } 47 | 48 | setConfig(config) { 49 | if (!config.theme) { 50 | throw new Error('No house type defined'); 51 | } 52 | 53 | if (THEMES[config.theme]) { 54 | this.theme = THEMES[config.theme]; 55 | } else if (config.custom_themes[config.theme]) { 56 | this.theme = config.custom_themes[config.theme]; 57 | } else { 58 | throw new Error('Unsupported house type: ' + config.theme); 59 | } 60 | 61 | this.config = config; 62 | } 63 | 64 | getCardSize() { 65 | return 4; 66 | } 67 | 68 | render() { 69 | try { 70 | if (this.config.background == 'paper-card') { 71 | return html `${this.make_content()}`; 72 | } 73 | 74 | return this.make_content(); 75 | } catch (error) { 76 | return html ` 77 | 78 |
79 | ${error} 80 |
81 |
82 | `; 83 | } 84 | } 85 | 86 | make_content() { 87 | var weather = ""; 88 | var resources = ""; 89 | 90 | if (this.config.weather) { 91 | var weatherObj = this.stateObject('weather', this.config.weather); 92 | weather = html ` 93 |
94 | 95 | 96 | ${weatherObj.attributes.friendly_name} 97 | ${weatherObj.attributes.temperature}${this.hass.config.unit_system.temperature} 98 | 99 |
`; 100 | } 101 | 102 | if (this.config.resources) { 103 | resources = html ` 104 |
105 | ${this.config.resources.map(resource => this.make_resource(resource))} 106 |
`; 107 | } 108 | 109 | return html ` 110 |
111 | ${weather} 112 |
113 | 114 | ${this.make_entities()} 115 |
116 | ${resources} 117 |
118 | `; 119 | } 120 | 121 | make_resource(resource) { 122 | var stateObj = this.stateObject('resources', resource.entity); 123 | return html ` 124 | 127 | 128 | 129 | 130 | ${Math.round(stateObj.state) || stateObj.state} 131 | ${resource.unit_of_measurement || this.get_attribute(stateObj, 'unit_of_measurement', '')} 132 | 133 | 134 | `; 135 | } 136 | 137 | get_attribute(stateObj, name, _default) { 138 | if (!stateObj['attributes'] || !stateObj.attributes[name]) { 139 | return _default; 140 | } 141 | 142 | return stateObj.attributes[name]; 143 | } 144 | 145 | more_info(entity_id) { 146 | fireEvent(this, "hass-more-info", { entityId: entity_id }); 147 | } 148 | 149 | make_entities() { 150 | var to_add = [] 151 | Object.keys(this.config.entities).map(index => { 152 | var entity = this.config.entities[index]; 153 | 154 | if (!this.theme.overlays[entity.type]) { 155 | throw Error('Unsupported entity type: ' + entity.type); 156 | } 157 | 158 | var stateObj = this.stateObject('entities', entity.entity); 159 | 160 | var state = stateObj.state; 161 | if (entity.state_map && stateObj.state in entity.state_map) { 162 | state = entity.state_map[stateObj.state]; 163 | } 164 | 165 | var overlay = this.theme.overlays[entity.type][state]; 166 | if (overlay) { 167 | for (var i = 0; i < overlay.length; ++i) { 168 | var imageName = entity.type + '_' + stateObj.state + '_' + i; 169 | to_add.push(this.create_overlay( 170 | imageName, overlay[i].image, overlay[i].style, entity)); 171 | } 172 | } 173 | }); 174 | return to_add; 175 | } 176 | 177 | create_overlay(imageName, imageFile, style, entity) { 178 | var styleString = Object.keys(style).map(prop => prop + ": " + style[prop] + ";"); 179 | return html ` 180 | 187 | ` 188 | } 189 | 190 | imgPath(filename) { 191 | return `/local/home-card/themes/${this.config.theme}/${filename}?v=${VERSION}`; 192 | } 193 | 194 | stateObject(source, entity_id) { 195 | if (!entity_id) { 196 | throw Error(`Empty entity id specified in ${source}`); 197 | } 198 | 199 | var stateObj = this.hass.states[entity_id]; 200 | if (!stateObj) { 201 | throw Error(`The entity "${entity_id}" does not exist (${source})`) 202 | } 203 | 204 | return stateObj; 205 | } 206 | 207 | // The function contains so much magic... 208 | get_entity_action(config, action) { 209 | // If action is specified for this entity, use that 210 | if (config[action]) { 211 | return config[action]; 212 | } 213 | 214 | // If no action is specified, use theme defined action 215 | if (this.theme.overlay_actions) { 216 | var overlayActions = this.theme.overlay_actions; 217 | 218 | // First check for specific overlay in theme 219 | if (overlayActions[config.type] && overlayActions[config.type][action]) { 220 | return overlayActions[config.type][action]; 221 | } 222 | 223 | // Next check default for all overlays in theme 224 | if (overlayActions['*'] && overlayActions['*'][action]) { 225 | return overlayActions['*'][action]; 226 | } 227 | } 228 | 229 | // If no theme action, fallback to default action 230 | return { action: 'more-info', }; 231 | } 232 | 233 | // Tap/hold for resources are hardcoded to more-info for now (maybe configurable in the future) 234 | get_resource_action(action) { 235 | return { 'action': 'more-info'}; 236 | } 237 | 238 | handleClick(config, actionConfig) { 239 | switch (actionConfig.action) { 240 | case "more-info": 241 | if (config.entity || config.camera_image) { 242 | fireEvent(this, "hass-more-info", { 243 | entityId: config.entity ? config.entity : config.camera_image, 244 | }); 245 | } 246 | break; 247 | case "navigate": 248 | if (actionConfig.navigation_path) { 249 | history.pushState(null, "", actionConfig.navigation_path); 250 | fireEvent(window, "location-changed"); 251 | } 252 | break; 253 | case "toggle": 254 | if (!config.entity) { 255 | return; 256 | } 257 | 258 | if (config.entity.startsWith("cover.")) { 259 | var coverState = this.hass.states[config.entity].state; 260 | this.hass.callService('cover', 261 | coverState == 'open' ? 'close_cover' : 'open_cover', 262 | {'entity_id': config.entity}); 263 | } else { 264 | this.hass.callService('homeassistant', 'toggle', {'entity_id': config.entity}); 265 | } 266 | break; 267 | case "call-service": { 268 | if (actionConfig.service) { 269 | const [domain, service] = actionConfig.service.split(".", 2); 270 | this.hass.callService(domain, service, actionConfig.service_data); 271 | } 272 | } 273 | } 274 | } 275 | 276 | _down(config) { 277 | if (!this.timer) { 278 | this.timer = window.setTimeout(() => { this.held = true; }, 500); 279 | this.held = false; 280 | } 281 | } 282 | 283 | _up(config, is_overlay) { 284 | if (this.timer) { 285 | clearTimeout(this.timer); 286 | this.timer = undefined; 287 | 288 | let actionConfig = undefined; 289 | if (is_overlay) { 290 | actionConfig = this.get_entity_action(config, this.held ? 'hold_action' : 'tap_action'); 291 | } else { 292 | actionConfig = this.get_resource_action(this.held ? 'hold_action' : 'tap_action') 293 | } 294 | this.handleClick(config, actionConfig); 295 | } 296 | } 297 | 298 | static get styles() { 299 | return css ` 300 | #root { 301 | width: 100%; 302 | height: auto; 303 | padding-top: 5%; 304 | padding-bottom: 5%; 305 | } 306 | #weather { 307 | position: relative; 308 | overflow: visible; 309 | height: 100%; 310 | width: 90%; 311 | left: 5%; 312 | margin-bottom: 25px; 313 | } 314 | #weather-icon { 315 | width: 15%; 316 | } 317 | #weather-info { 318 | position: absolute; 319 | top: 25%; 320 | margin-left: 20px; 321 | color: var(--primary-text-color); 322 | font-weight: 300; 323 | font-size: 2em; 324 | } 325 | #house { 326 | position: relative; 327 | overflow: visible; 328 | height: 100%; 329 | width: 90%; 330 | left: 5%; 331 | z-index: 1; 332 | } 333 | #house-image { 334 | top: 50%; 335 | width: 100%; 336 | } 337 | #resource-usage { 338 | width: 90%; 339 | left: 5%; 340 | height: 100%; 341 | position: relative; 342 | margin-top: 25px; 343 | display: grid; 344 | grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); 345 | grid-auto-rows: 20px; 346 | grid-gap: 5px; 347 | } 348 | .element { 349 | position: absolute; 350 | transform: translate(-50%, -50%); 351 | } 352 | .icon { 353 | color: var(--paper-item-icon-color, #44739e); 354 | display: inline-block; 355 | flex: 0 0 40px; 356 | line-height: 40px; 357 | position: relative; 358 | text-align: center; 359 | width: 40px; 360 | } 361 | .error-message { 362 | flex: 1; 363 | background-color: yellow; 364 | padding: 1em; 365 | } 366 | `; 367 | } 368 | } 369 | 370 | customElements.define('home-card', HomeCard); 371 | -------------------------------------------------------------------------------- /images/card-editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/images/card-editor.png -------------------------------------------------------------------------------- /images/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/images/demo.gif -------------------------------------------------------------------------------- /images/ranch_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/images/ranch_home.png -------------------------------------------------------------------------------- /images/structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/images/structure.png -------------------------------------------------------------------------------- /themes.js: -------------------------------------------------------------------------------- 1 | export const THEMES = { 2 | 'two_story_with_garage': { 3 | 'house': 'house.png', 4 | 'overlay_actions': { 5 | '*': { 6 | 'tap_action': { 7 | 'action': 'toggle', 8 | }, 9 | 'hold_action': { 10 | 'action': 'more-info', 11 | }, 12 | }, 13 | 'car': { 14 | 'tap_action': { 15 | 'action': 'more-info', 16 | }, 17 | }, 18 | 'sprinkler': { 19 | 'tap_action': { 20 | 'action': 'more-info', 21 | }, 22 | }, 23 | }, 24 | 'overlays': { 25 | 'door': { 26 | 'on': [ 27 | { 28 | 'image': 'door-close.png', 29 | 'style': { 'width': '8%', 'left': '40%', 'top': '68.5%', 'z-index': '10'}, 30 | } 31 | ], 32 | 'off': [ 33 | { 34 | 'image': 'door-open.png', 35 | 'style': { 'width': '8%', 'left': '40%', 'top': '68.5%', 'z-index': '10'}, 36 | }, 37 | ], 38 | }, 39 | 'garage': { 40 | 'open': [ 41 | { 42 | 'image': 'garage-open.png', 43 | 'style': { 'width': '21%', 'left': '73.5%', 'top': '67.5%', 'z-index': '10' }, 44 | }, 45 | ], 46 | 'closed': [ 47 | { 48 | 'image': 'garage-close.png', 49 | 'style': { 'width': '21%', 'left': '73.5%', 'top': '67.5%', 'z-index': '10' }, 50 | }, 51 | ], 52 | }, 53 | 'outside_light': { 54 | 'on': [ 55 | { 56 | 'image': 'outside-light-on.png', 57 | 'style': { 'width': '8%', 'left': '10%', 'top': '77%', 'z-index': '10' }, 58 | }, 59 | { 60 | 'image': 'outside-light-on.png', 61 | 'style': { 'width': '8%', 'left': '56%', 'top': '77%', 'z-index': '10' }, 62 | }, 63 | { 64 | 'image': 'outside-light-on.png', 65 | 'style': { 'width': '8%', 'left': '91%', 'top': '77%', 'z-index': '10' }, 66 | }, 67 | ], 68 | 'off': [ 69 | { 70 | 'image': 'outside-light-off.png', 71 | 'style': { 'width': '8%', 'left': '10%', 'top': '77%', 'z-index': '10' }, 72 | }, 73 | { 74 | 'image': 'outside-light-off.png', 75 | 'style': { 'width': '8%', 'left': '56%', 'top': '77%', 'z-index': '10' }, 76 | }, 77 | { 78 | 'image': 'outside-light-off.png', 79 | 'style': { 'width': '8%', 'left': '91%', 'top': '77%', 'z-index': '10' }, 80 | }, 81 | ], 82 | }, 83 | 'downstairs_light': { 84 | 'on': [ 85 | { 86 | 'image': 'window-light.png', 87 | 'style': { 'width': '6%', 'left': '56%', 'top': '61%', 'z-index': '10' }, 88 | }, 89 | { 90 | 'image': 'window-light.png', 91 | 'style': { 'width': '6%', 'left': '17%', 'top': '61%', 'z-index': '10' }, 92 | }, 93 | { 94 | 'image': 'window-light.png', 95 | 'style': { 'width': '6%', 'left': '25%', 'top': '61%', 'z-index': '10' }, 96 | }, 97 | ], 98 | 'off': [ 99 | { 100 | 'image': 'window-dark.png', 101 | 'style': { 'width': '6%', 'left': '56%', 'top': '61%', 'z-index': '10' }, 102 | }, 103 | { 104 | 'image': 'window-dark.png', 105 | 'style': { 'width': '6%', 'left': '17%', 'top': '61%', 'z-index': '10' }, 106 | }, 107 | { 108 | 'image': 'window-dark.png', 109 | 'style': { 'width': '6%', 'left': '25%', 'top': '61%', 'z-index': '10' }, 110 | }, 111 | ] 112 | }, 113 | 'upstairs_light': { 114 | 'on': [ 115 | { 116 | 'image': 'window-light.png', 117 | 'style': { 'width': '6%', 'left': '33%', 'top': '25%', 'z-index': '10' }, 118 | }, 119 | ], 120 | 'off': [ 121 | { 122 | 'image': 'window-dark.png', 123 | 'style': { 'width': '6%', 'left': '33%', 'top': '25%', 'z-index': '10' }, 124 | }, 125 | ] 126 | }, 127 | 'car': { 128 | 'home': [ 129 | { 130 | 'image': 'car.png', 131 | 'style': { 'width': '18%', 'left': '73.5%', 'top': '85%', 'z-index': '10' }, 132 | }, 133 | ], 134 | }, 135 | 'sprinkler': { 136 | 'on': [ 137 | { 138 | 'image': 'sprinkler-on.png', 139 | 'style': { 'left': '23%', 'top': '86%', 'z-index': '10' }, 140 | }, 141 | { 142 | 'image': 'sprinkler-on.png', 143 | 'style': { 'left': '50%', 'top': '89%', 'z-index': '10' }, 144 | }, 145 | ], 146 | 'off': [ 147 | { 148 | 'image': 'sprinkler-off.png', 149 | 'style': { 'left': '23%', 'top': '86%', 'z-index': '10' }, 150 | }, 151 | { 152 | 'image': 'sprinkler-off.png', 153 | 'style': { 'left': '50%', 'top': '89%', 'z-index': '10' }, 154 | }, 155 | ], 156 | }, 157 | }, 158 | }, 159 | 'ranch_with_three_stall_garage': { 160 | 'house': 'house.png', 161 | 'overlay_actions': { 162 | '*': { 163 | 'tap_action': { 164 | 'action': 'toggle', 165 | }, 166 | 'hold_action': { 167 | 'action': 'more-info', 168 | }, 169 | }, 170 | 'car': { 171 | 'tap_action': { 172 | 'action': 'more-info', 173 | }, 174 | }, 175 | 'car2': { 176 | 'tap_action': { 177 | 'action': 'more-info', 178 | }, 179 | }, 180 | 'car3': { 181 | 'tap_action': { 182 | 'action': 'more-info', 183 | }, 184 | }, 185 | 'sprinkler': { 186 | 'tap_action': { 187 | 'action': 'more-info', 188 | }, 189 | }, 190 | }, 191 | 'overlays': { 192 | 'door': { 193 | 'on': [ 194 | { 195 | 'image': 'door-close.png', 196 | 'style': { 'width': '5.8%', 'left': '32.11%', 'top': '61%', 'z-index': '10'}, 197 | } 198 | ], 199 | 'off': [ 200 | { 201 | 'image': 'door-open.png', 202 | 'style': { 'width': '5.8%', 'left': '32.11%', 'top': '61%', 'z-index': '10'}, 203 | }, 204 | ], 205 | }, 206 | 'garage': { 207 | 'open': [ 208 | { 209 | 'image': 'garage-open.png', 210 | 'style': { 'width': '23%', 'height': '34%', 'left': '61.2%', 'top': '57.5%', 'z-index': '10' }, 211 | }, 212 | ], 213 | 'closed': [ 214 | { 215 | 'image': 'garage-close.png', 216 | 'style': { 'width': '23%', 'height': '34%', 'left': '61.2%', 'top': '57.5%', 'z-index': '10' }, 217 | }, 218 | ], 219 | }, 220 | 'garage2': { 221 | 'open': [ 222 | { 223 | 'image': 'garage-open.png', 224 | 'style': { 'width': '13%', 'height': '34%', 'left': '83.7%', 'top': '57.5%', 'z-index': '10', 'filter': 'contrast(80%)' }, 225 | } 226 | ], 227 | 'closed': [ 228 | { 229 | 'image': 'garage-close.png', 230 | 'style': { 'width': '13%', 'height': '34%', 'left': '83.7%', 'top': '57.5%', 'z-index': '10', 'filter': 'contrast(80%)' }, 231 | } 232 | ], 233 | }, 234 | 'outside_light': { 235 | 'on': [ 236 | { 237 | 'image': 'outside-light-on.png', 238 | 'style': { 'width': '6%', 'left': '12.3%', 'top': '70.5%', 'z-index': '10' }, 239 | }, 240 | { 241 | 'image': 'outside-light-on.png', 242 | 'style': { 'width': '6%', 'left': '21.2%', 'top': '70.5%', 'z-index': '10' }, 243 | }, 244 | { 245 | 'image': 'outside-light-on.png', 246 | 'style': { 'width': '6%', 'left': '42.8%', 'top': '70.5%', 'z-index': '10' }, 247 | }, 248 | ], 249 | 'off': [ 250 | { 251 | 'image': 'outside-light-off.png', 252 | 'style': { 'width': '6%', 'left': '12.3%', 'top': '70.5%', 'z-index': '10' }, 253 | }, 254 | { 255 | 'image': 'outside-light-off.png', 256 | 'style': { 'width': '6%', 'left': '21.2%', 'top': '70.5%', 'z-index': '10' }, 257 | }, 258 | { 259 | 'image': 'outside-light-off.png', 260 | 'style': { 'width': '6%', 'left': '42.8%', 'top': '70.5%', 'z-index': '10' }, 261 | }, 262 | ], 263 | }, 264 | 'downstairs_light': { 265 | 'on': [ 266 | ], 267 | 'off': [ 268 | ] 269 | }, 270 | 'upstairs_light': { 271 | 'on': [ 272 | { 273 | 'image': 'window-light.png', 274 | 'style': { 'width': '4.5%', 'left': '15.5%', 'top': '53.6%', 'z-index': '10' }, 275 | }, 276 | { 277 | 'image': 'window-light.png', 278 | 'style': { 'width': '4.5%', 'left': '19.5%', 'top': '53.6%', 'z-index': '10' }, 279 | }, 280 | { 281 | 'image': 'window-light.png', 282 | 'style': { 'width': '4.5%', 'left': '42.3%', 'top': '53.6%', 'z-index': '10' }, 283 | }, 284 | ], 285 | 'off': [ 286 | { 287 | 'image': 'window-dark.png', 288 | 'style': { 'width': '4.5%', 'left': '15.5%', 'top': '53.6%', 'z-index': '10' }, 289 | }, 290 | { 291 | 'image': 'window-dark.png', 292 | 'style': { 'width': '4.5%', 'left': '19.5%', 'top': '53.6%', 'z-index': '10' }, 293 | }, 294 | { 295 | 'image': 'window-dark.png', 296 | 'style': { 'width': '4.5%', 'left': '42.3%', 'top': '53.6%', 'z-index': '10' }, 297 | }, 298 | ] 299 | }, 300 | 'car': { 301 | 'home': [ 302 | { 303 | 'image': 'car.png', 304 | 'style': { 'width': '11%', 'left': '55.2%', 'top': '72%', 'z-index': '10' }, 305 | }, 306 | ], 307 | }, 308 | 'car2': { 309 | 'home': [ 310 | { 311 | 'image': 'car.png', 312 | 'style': { 'width': '11%', 'left': '67.2%', 'top': '72%', 'z-index': '10' }, 313 | }, 314 | ], 315 | }, 316 | 'car3': { 317 | 'home': [ 318 | { 319 | 'image': 'car.png', 320 | 'style': { 'width': '11%', 'left': '84%', 'top': '72%', 'z-index': '10' }, 321 | }, 322 | ], 323 | }, 324 | 'sprinkler': { 325 | 'on': [ 326 | { 327 | 'image': 'sprinkler-on.png', 328 | 'style': { 'width': '6%', 'left': '18%', 'top': '74%', 'z-index': '10' }, 329 | }, 330 | { 331 | 'image': 'sprinkler-on.png', 332 | 'style': { 'width': '6%', 'left': '40%', 'top': '78%', 'z-index': '10' }, 333 | }, 334 | ], 335 | 'off': [ 336 | { 337 | 'image': 'sprinkler-off.png', 338 | 'style': { 'width': '6%', 'left': '18%', 'top': '74%', 'z-index': '10' }, 339 | }, 340 | { 341 | 'image': 'sprinkler-off.png', 342 | 'style': { 'width': '6%', 'left': '40%', 'top': '78%', 'z-index': '10' }, 343 | }, 344 | ], 345 | }, 346 | }, 347 | }, 348 | }; -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/car.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/door-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/door-close.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/door-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/door-open.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/garage-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/garage-close.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/garage-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/garage-open.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/house.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/house.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/outside-light-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/outside-light-off.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/outside-light-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/outside-light-on.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/sprinkler-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/sprinkler-off.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/sprinkler-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/sprinkler-on.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/utility-electricity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/utility-electricity.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/utility-water.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/utility-water.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-cloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-cloudy.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-exceptional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-exceptional.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-fog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-fog.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-hail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-hail.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-lightning-rainy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-lightning-rainy.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-lightning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-lightning.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-partlycloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-partlycloudy.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-pouring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-pouring.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-rainy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-rainy.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-snowy-rainy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-snowy-rainy.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-snowy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-snowy.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-sun.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-sunny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-sunny.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-windy-variant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-windy-variant.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/weather-windy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/weather-windy.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/window-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/window-dark.png -------------------------------------------------------------------------------- /themes/ranch_with_three_stall_garage/window-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/ranch_with_three_stall_garage/window-light.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/car.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/door-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/door-close.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/door-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/door-open.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/garage-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/garage-close.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/garage-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/garage-open.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/house.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/house.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/outside-light-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/outside-light-off.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/outside-light-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/outside-light-on.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/sprinkler-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/sprinkler-off.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/sprinkler-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/sprinkler-on.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/utility-electricity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/utility-electricity.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/utility-water.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/utility-water.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-cloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-cloudy.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-exceptional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-exceptional.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-fog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-fog.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-hail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-hail.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-lightning-rainy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-lightning-rainy.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-lightning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-lightning.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-partlycloudy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-partlycloudy.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-pouring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-pouring.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-rainy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-rainy.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-snowy-rainy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-snowy-rainy.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-snowy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-snowy.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-sun.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-sunny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-sunny.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-windy-variant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-windy-variant.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/weather-windy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/weather-windy.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/window-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/window-dark.png -------------------------------------------------------------------------------- /themes/two_story_with_garage/window-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postlund/home-card/8d21f1addbc8718450d4e31804be0aaba8b5bec9/themes/two_story_with_garage/window-light.png --------------------------------------------------------------------------------