├── automations.yaml ├── configuration.yaml ├── custom_components └── customizer │ ├── __init__.py │ └── services.yaml ├── groups.yaml ├── helm.yaml ├── packages ├── loc_zane.yaml ├── obd.yaml ├── speedify.yaml └── verizon.yaml ├── scripts.yaml ├── themes ├── google-home.yaml └── light-navy-blue.yaml ├── update.sh └── www ├── card-mod.js ├── custom_ui ├── scripts-es5.js.LICENSE ├── scripts-es5.js.map ├── scripts.js.LICENSE ├── scripts.js.map ├── state-card-custom-ui-es5.html ├── state-card-custom-ui-es5.html.gz ├── state-card-custom-ui.html └── state-card-custom-ui.html.gz ├── kiosk.css ├── kiosk.js ├── mini-graph-card-bundle.js ├── monster-card.js └── photos ├── van-overhead.jpg └── van-side.jpg /automations.yaml: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /configuration.yaml: -------------------------------------------------------------------------------- 1 | homeassistant: 2 | packages: !include_dir_named packages 3 | customize_glob: 4 | "sensor.speedify_status_*": 5 | templates: 6 | friendly_name: >- 7 | if (state === 'disconnected') return 'disconnected'; 8 | else if (attributes.type == 'Wi-Fi') return attributes.connectedNetworkName; 9 | else return attributes.type; 10 | icon: >- 11 | if (state === 'disconnected') { 12 | if (attributes.type == 'Wi-Fi') return 'mdi:wifi-strength-off-outline'; 13 | else return 'mdi:signal-off'; 14 | } 15 | else if (attributes.type == 'Wi-Fi') return 'mdi:wifi-strength-4'; 16 | else return 'mdi:signal-4g'; 17 | auth_providers: 18 | - type: homeassistant 19 | # - type: trusted_networks 20 | # allow_bypass_login: true 21 | # trusted_networks: 22 | # - !secret ip_self 23 | # trusted_users: 24 | # !secret ip_local_network_all: !secret guest_user 25 | 26 | http: 27 | server_port: 8123 28 | base_url: !secret base_url 29 | use_x_forwarded_for: true 30 | trusted_proxies: 31 | - 127.0.0.1 32 | - !secret gateway 33 | cors_allowed_origins: 34 | - https://google.com 35 | - https://www.home-assistant.io 36 | # - http://house.local 37 | ip_ban_enabled: false 38 | 39 | # custom_updater: 40 | # show_installable: false 41 | # hide_sensor: false 42 | # track: 43 | # - components 44 | # - cards 45 | # - python_scripts 46 | # component_urls: 47 | # - https://raw.githubusercontent.com/keatontaylor/custom_components/master/custom_components.json 48 | # card_urls: 49 | # - https://raw.githubusercontent.com/kalkih/mini-media-player/master/tracker.json 50 | # - https://raw.githubusercontent.com/kalkih/mini-graph-card/master/tracker.json 51 | 52 | frontend: 53 | javascript_version: latest 54 | themes: !include_dir_merge_named themes 55 | extra_html_url: 56 | - /local/custom_ui/state-card-custom-ui.html 57 | extra_html_url_es5: 58 | - /local/custom_ui/state-card-custom-ui-es5.html 59 | 60 | # Configure a default setup of Home Assistant (frontend, api, etc) 61 | default_config: 62 | 63 | # Text to speech 64 | tts: 65 | - platform: google_translate 66 | 67 | group: !include groups.yaml 68 | automation: !include automations.yaml 69 | script: !include scripts.yaml 70 | 71 | mqtt: 72 | broker: !secret ip_self 73 | -------------------------------------------------------------------------------- /custom_components/customizer/__init__.py: -------------------------------------------------------------------------------- 1 | """Customizer component. Bring extra customize features to home-assistant.""" 2 | 3 | import asyncio 4 | import logging 5 | import os 6 | 7 | import homeassistant.components.frontend as frontend 8 | import homeassistant.helpers.config_validation as cv 9 | from homeassistant.config import load_yaml_config_file, DATA_CUSTOMIZE 10 | from homeassistant.core import callback 11 | 12 | from homeassistant.helpers.entity import Entity 13 | from homeassistant.helpers.entity_component import EntityComponent 14 | from homeassistant.const import CONF_ENTITY_ID, MINOR_VERSION 15 | 16 | import voluptuous as vol 17 | 18 | _LOGGER = logging.getLogger(__name__) 19 | 20 | DOMAIN = 'customizer' 21 | DEPENDENCIES = ['frontend'] 22 | 23 | CONF_CUSTOM_UI = 'custom_ui' 24 | 25 | LOCAL = 'local' 26 | HOSTED = 'hosted' 27 | DEBUG = 'debug' 28 | 29 | CONF_HIDE_ATTRIBUTES = 'hide_attributes' 30 | 31 | CONF_ATTRIBUTE = 'attribute' 32 | CONF_VALUE = 'value' 33 | CONF_COLUMNS = 'columns' 34 | 35 | SERVICE_SET_ATTRIBUTE = 'set_attribute' 36 | SERVICE_SET_ATTRIBUTE_SCHEMA = vol.Schema({ 37 | vol.Required(CONF_ENTITY_ID): cv.entity_id, 38 | vol.Required(CONF_ATTRIBUTE): cv.string, 39 | vol.Optional(CONF_VALUE): cv.match_all, 40 | }) 41 | 42 | CONFIG_SCHEMA = vol.Schema({ 43 | DOMAIN: vol.Schema({ 44 | vol.Optional(CONF_CUSTOM_UI): cv.string, 45 | vol.Optional(CONF_COLUMNS): [int], 46 | vol.Optional(CONF_HIDE_ATTRIBUTES): 47 | vol.All(cv.ensure_list, [cv.string]), 48 | }) 49 | }, extra=vol.ALLOW_EXTRA) 50 | 51 | 52 | @asyncio.coroutine 53 | def async_setup(hass, config): 54 | """Set up customizer.""" 55 | custom_ui = config[DOMAIN].get(CONF_CUSTOM_UI) 56 | if MINOR_VERSION < 53 and custom_ui is not None: 57 | _LOGGER.warning('%s is only supported from Home Assistant 0.53', 58 | CONF_CUSTOM_UI) 59 | elif custom_ui is not None: 60 | def add_extra_html_url(base_url): 61 | """Add extra url using version-dependent function.""" 62 | if MINOR_VERSION >= 59: 63 | frontend.add_extra_html_url( 64 | hass, '{}.html'.format(base_url), False) 65 | frontend.add_extra_html_url( 66 | hass, '{}-es5.html'.format(base_url), True) 67 | else: 68 | frontend.add_extra_html_url(hass, '{}.html'.format(base_url)) 69 | 70 | if custom_ui == LOCAL: 71 | add_extra_html_url('/local/custom_ui/state-card-custom-ui') 72 | elif custom_ui == HOSTED: 73 | add_extra_html_url( 74 | 'https://raw.githubusercontent.com/andrey-git/' 75 | 'home-assistant-custom-ui/master/state-card-custom-ui') 76 | elif custom_ui == DEBUG: 77 | add_extra_html_url( 78 | 'https://raw.githubusercontent.com/andrey-git/' 79 | 'home-assistant-custom-ui/master/' 80 | 'state-card-custom-ui-dbg') 81 | else: 82 | add_extra_html_url( 83 | 'https://github.com/andrey-git/home-assistant-custom-ui/' 84 | 'releases/download/{}/state-card-custom-ui' 85 | .format(custom_ui)) 86 | 87 | component = EntityComponent(_LOGGER, DOMAIN, hass) 88 | yield from component.async_add_entities([CustomizerEntity(config[DOMAIN])]) 89 | 90 | @callback 91 | def set_attribute(call): 92 | """Set attribute override.""" 93 | data = call.data 94 | entity_id = data[CONF_ENTITY_ID] 95 | attribute = data[CONF_ATTRIBUTE] 96 | value = data.get(CONF_VALUE) 97 | overrides = hass.data[DATA_CUSTOMIZE].get(entity_id) 98 | state = hass.states.get(entity_id) 99 | state_attributes = dict(state.attributes) 100 | if value is None: 101 | if attribute in overrides: 102 | overrides.pop(attribute) 103 | if attribute in state_attributes: 104 | state_attributes.pop(attribute) 105 | else: 106 | overrides[attribute] = value 107 | state_attributes[attribute] = value 108 | hass.states.async_set(entity_id, state.state, state_attributes) 109 | 110 | if MINOR_VERSION >= 61: 111 | hass.services.async_register(DOMAIN, SERVICE_SET_ATTRIBUTE, 112 | set_attribute, 113 | SERVICE_SET_ATTRIBUTE_SCHEMA) 114 | else: 115 | descriptions = yield from hass.async_add_job( 116 | load_yaml_config_file, os.path.join( 117 | os.path.dirname(__file__), 'services.yaml')) 118 | hass.services.async_register(DOMAIN, SERVICE_SET_ATTRIBUTE, 119 | set_attribute, 120 | descriptions[SERVICE_SET_ATTRIBUTE], 121 | SERVICE_SET_ATTRIBUTE_SCHEMA) 122 | 123 | return True 124 | 125 | 126 | class CustomizerEntity(Entity): 127 | """Customizer entity class.""" 128 | 129 | def __init__(self, config): 130 | """Constructor that parses the config.""" 131 | self.hide_attributes = config.get(CONF_HIDE_ATTRIBUTES) 132 | self.columns = config.get(CONF_COLUMNS) 133 | 134 | @property 135 | def hidden(self): 136 | """Don't show the entity.""" 137 | return True 138 | 139 | @property 140 | def name(self): 141 | """Singleton name.""" 142 | return DOMAIN 143 | 144 | @property 145 | def state_attributes(self): 146 | """Return the state attributes.""" 147 | result = {} 148 | if self.hide_attributes: 149 | result[CONF_HIDE_ATTRIBUTES] = self.hide_attributes 150 | if self.columns: 151 | result[CONF_COLUMNS] = self.columns 152 | return result 153 | -------------------------------------------------------------------------------- /custom_components/customizer/services.yaml: -------------------------------------------------------------------------------- 1 | set_attribute: 2 | description: > 3 | Set or clear persistent attribute of an entity overriding any value set in code. 4 | Note that calling homeassistant.reload_core_config will reset overrides to their yaml state. 5 | fields: 6 | entity_id: 7 | description: Entity ID to set the attribute on. 8 | example: light.patio 9 | attribute: 10 | description: Name of the attribute to set. 11 | example: friendly_name 12 | value: 13 | description: > 14 | (Optional) Value to set. Leave unspecified in order to clear set value. 15 | Note that when clearing attribute it will be empty (and not set-by-code) until next entity update. 16 | example: 'My light' 17 | -------------------------------------------------------------------------------- /groups.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaneclaes/van-home-assistant-config/907196e279a1f9bccc25649bf42c1c99773e50c1/groups.yaml -------------------------------------------------------------------------------- /helm.yaml: -------------------------------------------------------------------------------- 1 | hostNetwork: true 2 | 3 | image: 4 | tag: 0.100.3 5 | 6 | persistence: 7 | hostPath: /home/pi/home-assistant 8 | 9 | # hostMounts: 10 | # - name: zha 11 | # hostPath: /dev/serial/by-id/usb-Silicon_Labs_HubZ_Smart_Home_Controller_6120245D-if01-port0 12 | # - name: zwave 13 | # hostPath: /dev/serial/by-id/usb-Silicon_Labs_HubZ_Smart_Home_Controller_6120245D-if00-port0 14 | -------------------------------------------------------------------------------- /packages/loc_zane.yaml: -------------------------------------------------------------------------------- 1 | sensor: 2 | - name: 'ZanePhone' 3 | platform: mqtt 4 | state_topic: 'owntracks/zane/D1B72C3A-923A-437D-9ABE-8E4416216C6F' 5 | json_attributes_topic: 'owntracks/zane/D1B72C3A-923A-437D-9ABE-8E4416216C6F' 6 | value_template: '{{value_json.batt}}' 7 | 8 | # "batt":98,"lon":-97.997737509999951,"acc":9785,"p":95.547836303710938,"bs":1,"vac":45,"lat":40.875564669999989,"t":"t","conn":"w","tst":1573599940,"alt":534,"_type":"location","tid":"6F" -------------------------------------------------------------------------------- /packages/obd.yaml: -------------------------------------------------------------------------------- 1 | sensor: 2 | - name: 'Car Speed' 3 | platform: mqtt 4 | state_topic: '/obd/speed' 5 | value_template: '{{value | int}}' 6 | force_update: true 7 | unit_of_measurement: 'Mph' 8 | icon: 'mdi:speedometer' 9 | 10 | - name: 'Car RPM' 11 | platform: mqtt 12 | state_topic: '/obd/rpm' 13 | value_template: '{{value | float | round(2)}}' 14 | force_update: true 15 | unit_of_measurement: 'rpm' 16 | icon: 'mdi:engine' 17 | 18 | - name: 'Car Control Module Voltage' 19 | platform: mqtt 20 | state_topic: '/obd/control_module_voltage' 21 | value_template: '{{value | float | round(2)}}' 22 | force_update: true 23 | unit_of_measurement: 'v' 24 | icon: 'mdi:flash' 25 | 26 | - name: 'Car ELM Voltage' 27 | platform: mqtt 28 | state_topic: '/obd/elm_voltage' 29 | value_template: '{{value | float | round(2)}}' 30 | force_update: true 31 | unit_of_measurement: 'v' 32 | icon: 'mdi:flash' 33 | 34 | - name: 'Car Fuel Level' 35 | platform: mqtt 36 | state_topic: '/obd/fuel_level' 37 | value_template: '{{value | float | round(2)}}' 38 | force_update: true 39 | unit_of_measurement: '%' 40 | icon: 'mdi:gas-station' 41 | 42 | - name: 'Car Ambient Air Temp' 43 | platform: mqtt 44 | state_topic: '/obd/ambiant_air_temp' 45 | value_template: '{{value | float | round(2)}}' 46 | force_update: true 47 | unit_of_measurement: 'F' 48 | icon: 'mdi:thermometer-lines' 49 | 50 | - name: 'Car Barometric Pressure' 51 | platform: mqtt 52 | state_topic: '/obd/barometric_pressure' 53 | value_template: '{{value | float | round(2)}}' 54 | force_update: true 55 | unit_of_measurement: 'kPa' 56 | icon: 'mdi:weight' 57 | 58 | - name: 'Car Run Time' 59 | platform: mqtt 60 | state_topic: '/obd/run_time' 61 | value_template: '{{value | float | round(2)}}' 62 | force_update: true 63 | unit_of_measurement: 's' 64 | icon: 'mdi:timer' 65 | 66 | - name: 'Car Accelerator Position (D)' 67 | platform: mqtt 68 | state_topic: '/obd/accelerator_pos_d' 69 | value_template: '{{value | float | round(2)}}' 70 | force_update: true 71 | unit_of_measurement: '%' 72 | icon: 'mdi:van-utility' 73 | 74 | - name: 'Car Accelerator Position (E)' 75 | platform: mqtt 76 | state_topic: '/obd/accelerator_pos_e' 77 | value_template: '{{value | float | round(2)}}' 78 | force_update: true 79 | unit_of_measurement: '%' 80 | icon: 'mdi:van-utility' 81 | 82 | - name: 'Car Throttle Position' 83 | platform: mqtt 84 | state_topic: '/obd/throttle_pos' 85 | value_template: '{{value | float | round(2)}}' 86 | force_update: true 87 | unit_of_measurement: '%' 88 | icon: 'mdi:van-utility' 89 | 90 | - name: 'Car Throttle Position (B)' 91 | platform: mqtt 92 | state_topic: '/obd/throttle_pos_b' 93 | value_template: '{{value | float | round(2)}}' 94 | force_update: true 95 | unit_of_measurement: '%' 96 | icon: 'mdi:van-utility' 97 | 98 | - name: 'Car Throttle Actuator' 99 | platform: mqtt 100 | state_topic: '/obd/throttle_actuator' 101 | value_template: '{{value | float | round(2)}}' 102 | force_update: true 103 | unit_of_measurement: '%' 104 | icon: 'mdi:van-utility' 105 | 106 | - name: 'Car Relative Throttle Position' 107 | platform: mqtt 108 | state_topic: '/obd/relative_throttle_pos' 109 | value_template: '{{value | float | round(2)}}' 110 | force_update: true 111 | unit_of_measurement: '%' 112 | icon: 'mdi:van-utility' 113 | 114 | - name: 'Car Coolant Temp' 115 | platform: mqtt 116 | state_topic: '/obd/coolant_temp' 117 | value_template: '{{value | float | round(2)}}' 118 | force_update: true 119 | unit_of_measurement: 'F' 120 | icon: 'mdi:thermometer-lines' 121 | 122 | - name: 'Car Intake Temp' 123 | platform: mqtt 124 | state_topic: '/obd/intake_temp' 125 | value_template: '{{value | float | round(2)}}' 126 | force_update: true 127 | unit_of_measurement: 'F' 128 | icon: 'mdi:thermometer-lines' 129 | 130 | - name: 'Car Engine Load' 131 | platform: mqtt 132 | state_topic: '/obd/engine_load' 133 | value_template: '{{value | float | round(2)}}' 134 | force_update: true 135 | unit_of_measurement: '%' 136 | icon: 'mdi:van-utility' 137 | 138 | - name: 'Car Absolute Load' 139 | platform: mqtt 140 | state_topic: '/obd/absolute_load' 141 | value_template: '{{value | float | round(2)}}' 142 | force_update: true 143 | unit_of_measurement: '%' 144 | icon: 'mdi:van-utility' 145 | -------------------------------------------------------------------------------- /packages/speedify.yaml: -------------------------------------------------------------------------------- 1 | sensor: 2 | - name: 'Speedify Status Verizon Jetpack' 3 | platform: mqtt 4 | state_topic: '/speedify/eth1' 5 | json_attributes_topic: '/speedify/eth1' 6 | value_template: '{{value_json.state}}' 7 | 8 | - name: 'Speedify Status WiFi' 9 | platform: mqtt 10 | state_topic: '/speedify/wlan1' 11 | json_attributes_topic: '/speedify/wlan1' 12 | value_template: '{{value_json.state}}' 13 | 14 | - name: 'Speedify Speed - Ping' 15 | platform: mqtt 16 | state_topic: '/speedify/speedtest/speedify' 17 | json_attributes_topic: '/speedify/speedtest/speedify' 18 | value_template: '{{value_json.rttMs | int}}' 19 | icon: 'mdi:speedometer' 20 | unit_of_measurement: 'ms' 21 | 22 | - platform: template 23 | sensors: 24 | speedify_speed_download: 25 | friendly_name_template: "Speedify Speed - Down" 26 | unit_of_measurement: 'Mbps' 27 | value_template: >- 28 | {{ ((states.sensor.speedify_speed_ping.attributes.downloadBps | float) / 1000000) | round(2) }} 29 | icon_template: 'mdi:download-network-outline' 30 | 31 | speedify_speed_upload: 32 | friendly_name_template: "Speedify Speed - Up" 33 | unit_of_measurement: 'Mbps' 34 | value_template: >- 35 | {{ ((states.sensor.speedify_speed_ping.attributes.uploadBps | float) / 1000000) | round(2) }} 36 | icon_template: 'mdi:upload-network-outline' 37 | -------------------------------------------------------------------------------- /packages/verizon.yaml: -------------------------------------------------------------------------------- 1 | sensor: 2 | - name: 'Verizon Usage Info' 3 | platform: mqtt 4 | state_topic: '/verizon/usage_info' 5 | json_attributes_topic: '/verizon/usage_info' 6 | value_template: '{{value_json.totalShrUsage | float | round(2)}}' # {{ value_json.unit }} 7 | force_update: true 8 | icon: 'mdi:access-point-network' 9 | unit_of_measurement: 'Gb' 10 | 11 | - name: 'Verizon Status Data' 12 | platform: mqtt 13 | state_topic: '/verizon/status_data' 14 | json_attributes_topic: '/verizon/status_data' 15 | value_template: '{{ ((value_json.statusBarBytesTotal | int) / 1000000000) | round(2) }}' 16 | unit_of_measurement: 'Gb' 17 | icon: 'mdi:wan' 18 | force_update: true 19 | 20 | - platform: template 21 | sensors: 22 | verizon_device: 23 | friendly_name_template: "{{ states.sensor.verizon_usage_info.attributes.gProductName }}" 24 | value_template: >- 25 | {{ states.sensor.verizon_status_data.attributes.statusBarNetwork }} 26 | icon_template: 'mdi:cellphone-wireless' 27 | 28 | # Icon = cell strength, 29 | verizon: 30 | friendly_name_template: "Verizon ({{ states.sensor.verizon_usage_info.attributes.daysLeft }} days left)" 31 | unit_of_measurement: 'Gb' 32 | value_template: >- 33 | {{ states.sensor.verizon_usage_info.state }} 34 | icon_template: > 35 | {% if states.sensor.verizon_status_data.attributes.statusBarConnectionState == 'Connected' %} 36 | {% if states.sensor.verizon_status_data.attributes.statusBarSignalBars | int <= 0 %} 37 | mdi:network-strength-outline 38 | {% elif states.sensor.verizon_status_data.attributes.statusBarSignalBars | int == 1 %} 39 | mdi:network-strength-1 40 | {% elif states.sensor.verizon_status_data.attributes.statusBarSignalBars | int == 2 %} 41 | mdi:network-strength-2 42 | {% elif states.sensor.verizon_status_data.attributes.statusBarSignalBars | int == 3 %} 43 | mdi:network-strength-3 44 | {% elif states.sensor.verizon_status_data.attributes.statusBarSignalBars | int >= 4 %} 45 | mdi:network-strength-4 46 | {% endif %} 47 | {% else %} 48 | mdi:network-strength-off-outline 49 | {% endif %} 50 | 51 | -------------------------------------------------------------------------------- /scripts.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaneclaes/van-home-assistant-config/907196e279a1f9bccc25649bf42c1c99773e50c1/scripts.yaml -------------------------------------------------------------------------------- /themes/google-home.yaml: -------------------------------------------------------------------------------- 1 | Google - Light: 2 | # accent: "#FF4081" 3 | # sidebar-selected-text-color: "var(--accent)" 4 | 5 | ### Fonts ### 6 | primary-font-family: "'Open Sans','Rubik',Roboto,sans-serif" 7 | paper-font-common-base_-_font-family: "var(--primary-font-family)" 8 | paper-font-common-code_-_font-family: "var(--primary-font-family)" 9 | paper-font-body_-_font-family: "var(--primary-font-family)" 10 | paper-font-subhead_-_font-family: "var(--primary-font-family)" 11 | paper-font-headline_-_font-family: "var(--primary-font-family)" 12 | paper-font-caption_-_font-family: "var(--primary-font-family)" 13 | paper-font-title_-_font-family: "var(--primary-font-family)" 14 | 15 | ha-card-border-radius: "5px" 16 | ha-card-header-color: "#757575" 17 | ha-card-header-background-color: "#eeeeee" 18 | ha-card-header-padding: "8px 16px 6px" 19 | ha-card-box-shadow: "0px 0px 1px #eeeeee" 20 | 21 | ### Main Interface Colors ### 22 | primary-color: "#ffffff" 23 | light-primary-color: "#c1c1c1" 24 | primary-background-color: "#eeeeee" # "#F7F9FB" 25 | secondary-background-color: "#ffffff" 26 | divider-color: "#e7e7e7" 27 | paper-icon-button-active-color: "#061014" 28 | paper-icon-button-inactive-color: "#a1a1a1" 29 | ### Text ### 30 | primary-text-color: "#000000" 31 | secondary-text-color: "#757575" 32 | text-primary-color: "#061014" 33 | disabled-text-color: "#a1a1a1" 34 | ### Sidebar Menu ### 35 | sidebar-background-color: "#ffffff" 36 | sidebar-icon-color: "#757575" 37 | sidebar-text-color: "#212121" 38 | sidebar-selected-background-color: var(--primary-background-color) 39 | sidebar-selected-icon-color: "#4284F4" 40 | sidebar-selected-text-color: var(--sidebar-selected-icon-color) 41 | ### States and Badges ### 42 | state-icon-color: "#606367" 43 | state-icon-active-color: "#ffb750" 44 | state-icon-unavailable-color: var(--disabled-text-color) 45 | ### Sliders ### 46 | paper-slider-knob-color: "#4284F4" 47 | paper-slider-knob-start-color: "#8eb8ff" 48 | paper-slider-pin-color: "#8eb8ff" 49 | paper-slider-active-color: "#8eb8ff" 50 | paper-slider-secondary-color: var(--light-primary-color) 51 | paper-slider-container-color: "#e7e7e7" 52 | ### Labels ### 53 | label-badge-background-color: "#252B36" 54 | label-badge-text-color: "#F1F1F1" 55 | label-badge-red: "#6C7B9B" 56 | ### Cards ### 57 | paper-card-background-color: "#ffffff" 58 | paper-listbox-background-color: "#ffffff" 59 | ### Toggles ### 60 | paper-toggle-button-checked-button-color: "#4284F4" 61 | paper-toggle-button-checked-bar-color: "#4284F4" 62 | paper-toggle-button-unchecked-button-color: "#4284F4" 63 | paper-toggle-button-unchecked-bar-color: "#c1c1c1" 64 | 65 | ### Dialog ### 66 | paper-dialog-background-color: "#ffffff" 67 | 68 | ### Table row ### 69 | table-row-background-color: var(--primary-background-color) 70 | table-row-alternative-background-color: var(--secondary-background-color) 71 | 72 | iron-overlay-backdrop-background-color: "#ffffff" 73 | mdc-theme-primary: "#4284F4" 74 | 75 | Google - Dark: 76 | ### Fonts ### 77 | primary-font-family: "'Open Sans','Rubik',Roboto,sans-serif" 78 | paper-font-common-base_-_font-family: "var(--primary-font-family)" 79 | paper-font-common-code_-_font-family: "var(--primary-font-family)" 80 | paper-font-body_-_font-family: "var(--primary-font-family)" 81 | paper-font-subhead_-_font-family: "var(--primary-font-family)" 82 | paper-font-headline_-_font-family: "var(--primary-font-family)" 83 | paper-font-caption_-_font-family: "var(--primary-font-family)" 84 | paper-font-title_-_font-family: "var(--primary-font-family)" 85 | 86 | ha-card-border-radius: "0px" 87 | ha-card-header-color: "#d7d7d7" 88 | ha-card-box-shadow: "0px 0px 1px #000000" 89 | 90 | ### Main Interface Colors ### 91 | primary-color: "#000000" 92 | light-primary-color: "#2b2b2b" 93 | primary-background-color: "#000000" 94 | secondary-background-color: "#2b2b2b" 95 | divider-color: "#2b2b2b" 96 | paper-icon-button-active-color: "#ffffff" 97 | paper-icon-button-inactive-color: "#a1a1a1" 98 | ### Text ### 99 | primary-text-color: "#ffffff" 100 | secondary-text-color: "#d7d7d7" 101 | text-primary-color: "#ffffff" 102 | disabled-text-color: "#a1a1a1" 103 | ### Sidebar Menu ### 104 | sidebar-background-color: "#000000" 105 | sidebar-icon-color: "#ffffff" 106 | sidebar-text-color: "#ffffff" 107 | sidebar-selected-background-color: var(--primary-background-color) 108 | sidebar-selected-icon-color: "#4284F4" 109 | sidebar-selected-text-color: var(--sidebar-selected-icon-color) 110 | ### States and Badges ### 111 | state-icon-color: "#ffffff" 112 | state-icon-active-color: "#ffb750" 113 | state-icon-unavailable-color: var(--disabled-text-color) 114 | ### Sliders ### 115 | paper-slider-knob-color: "#4284F4" 116 | paper-slider-knob-start-color: "#8eb8ff" 117 | paper-slider-pin-color: "#8eb8ff" 118 | paper-slider-active-color: "#8eb8ff" 119 | paper-slider-secondary-color: var(--light-primary-color) 120 | paper-slider-container-color: "#a1a1a1" 121 | ### Labels ### 122 | label-badge-background-color: "#252B36" 123 | label-badge-text-color: "#F1F1F1" 124 | label-badge-red: "#6C7B9B" 125 | ### Cards ### 126 | paper-card-background-color: "#2b2b2b" 127 | paper-listbox-background-color: "#000000" 128 | ### Toggles ### 129 | paper-toggle-button-checked-button-color: "#4284F4" 130 | paper-toggle-button-checked-bar-color: "#4284F4" 131 | paper-toggle-button-unchecked-button-color: "#4284F4" 132 | paper-toggle-button-unchecked-bar-color: "#c1c1c1" 133 | 134 | ### Dialog ### 135 | paper-dialog-background-color: "#2b2b2b" 136 | 137 | ### Table row ### 138 | table-row-background-color: var(--primary-background-color) 139 | table-row-alternative-background-color: var(--secondary-background-color) 140 | 141 | iron-overlay-backdrop-background-color: "#000000" 142 | mdc-theme-primary: "#4284F4" 143 | 144 | Smart - Dark: 145 | ### Fonts ### 146 | primary-font-family: "'Open Sans','Rubik',Roboto,sans-serif" 147 | paper-font-common-base_-_font-family: "var(--primary-font-family)" 148 | paper-font-common-code_-_font-family: "var(--primary-font-family)" 149 | paper-font-body_-_font-family: "var(--primary-font-family)" 150 | paper-font-subhead_-_font-family: "var(--primary-font-family)" 151 | paper-font-headline_-_font-family: "var(--primary-font-family)" 152 | paper-font-caption_-_font-family: "var(--primary-font-family)" 153 | paper-font-title_-_font-family: "var(--primary-font-family)" 154 | 155 | ha-card-border-radius: "5px" 156 | 157 | ### Main Interface Colors ### 158 | primary-color: "#000000" 159 | light-primary-color: "#B5B5B5" 160 | primary-background-color: "#000000" 161 | secondary-background-color: var(--primary-background-color) 162 | divider-color: "#2a2a2a" 163 | ### Text ### 164 | primary-text-color: "#ffffff" 165 | secondary-text-color: "#ffffff" 166 | text-primary-color: "#ffffff" 167 | disabled-text-color: "#a1a1a1" 168 | ### Sidebar Menu ### 169 | sidebar-background-color: "#000000" 170 | sidebar-icon-color: "#B5B5B5" 171 | sidebar-text-color: "#ffffff" 172 | sidebar-selected-background-color: var(--primary-background-color) 173 | sidebar-selected-icon-color: "#4197FE" 174 | sidebar-selected-text-color: "#ffffff" 175 | ### States and Badges ### 176 | state-icon-color: "#B5B5B5" 177 | state-icon-active-color: "#ffb750" 178 | state-icon-unavailable-color: var(--disabled-text-color) 179 | ### Sliders ### 180 | paper-slider-knob-color: "#E59D37" 181 | paper-slider-knob-start-color: "#ffd89f" 182 | paper-slider-pin-color: "#ffd89f" 183 | paper-slider-active-color: "#ffd89f" 184 | paper-slider-secondary-color: var(--light-primary-color) 185 | paper-slider-container-color: "#4e4e4e" 186 | ### Labels ### 187 | label-badge-background-color: "#0057f5" 188 | label-badge-text-color: "#F1F1F1" 189 | label-badge-red: "#6C7B9B" 190 | ### Cards ### 191 | paper-card-background-color: "#2c2c2c" 192 | paper-listbox-background-color: var(--primary-background-color) 193 | ### Toggles ### 194 | paper-toggle-button-checked-button-color: "#ffb750" 195 | paper-toggle-button-checked-bar-color: "#ffb750" 196 | paper-toggle-button-unchecked-button-color: "#6da3ff" 197 | paper-toggle-button-unchecked-bar-color: "#c1c1c1" 198 | ### Table row ### 199 | table-row-background-color: var(--primary-background-color) 200 | table-row-alternative-background-color: var(--secondary-background-color) 201 | 202 | iron-overlay-backdrop-background-color: "#B5B5B5" 203 | mdc-theme-primary: "#4197FE" 204 | 205 | Smart - Light: 206 | ### Fonts ### 207 | primary-font-family: "'Open Sans','Rubik',Roboto,sans-serif" 208 | paper-font-common-base_-_font-family: "var(--primary-font-family)" 209 | paper-font-common-code_-_font-family: "var(--primary-font-family)" 210 | paper-font-body_-_font-family: "var(--primary-font-family)" 211 | paper-font-subhead_-_font-family: "var(--primary-font-family)" 212 | paper-font-headline_-_font-family: "var(--primary-font-family)" 213 | paper-font-caption_-_font-family: "var(--primary-font-family)" 214 | paper-font-title_-_font-family: "var(--primary-font-family)" 215 | 216 | ha-card-border-radius: "5px" 217 | 218 | ### Main Interface Colors ### 219 | primary-color: "#ffffff" 220 | light-primary-color: "#c1c1c1" 221 | primary-background-color: "#ffffff" 222 | secondary-background-color: var(--primary-background-color) 223 | divider-color: "#e7e7e7" 224 | ### Text ### 225 | primary-text-color: "#757575" 226 | secondary-text-color: "#757575" 227 | text-primary-color: "#757575" 228 | disabled-text-color: "#a1a1a1" 229 | ### Sidebar Menu ### 230 | sidebar-background-color: "#ffffff" 231 | sidebar-icon-color: "#757575" 232 | sidebar-text-color: "#212121" 233 | sidebar-selected-background-color: var(--primary-background-color) 234 | sidebar-selected-icon-color: "#4284F4" 235 | sidebar-selected-text-color: var(--sidebar-selected-icon-color) 236 | ### States and Badges ### 237 | state-icon-color: "#606367" 238 | state-icon-active-color: "#ffb750" 239 | state-icon-unavailable-color: var(--disabled-text-color) 240 | ### Sliders ### 241 | paper-slider-knob-color: "#E59D37" 242 | paper-slider-knob-start-color: "#ffd89f" 243 | paper-slider-pin-color: "#ffd89f" 244 | paper-slider-active-color: "#ffd89f" 245 | paper-slider-secondary-color: var(--light-primary-color) 246 | paper-slider-container-color: "#e7e7e7" 247 | ### Labels ### 248 | label-badge-background-color: "#252B36" 249 | label-badge-text-color: "#F1F1F1" 250 | label-badge-red: "#6C7B9B" 251 | ### Cards ### 252 | paper-card-background-color: "#ffffff" 253 | paper-listbox-background-color: var(--primary-background-color) 254 | ### Toggles ### 255 | paper-toggle-button-checked-button-color: "#ffb750" 256 | paper-toggle-button-checked-bar-color: "#ffb750" 257 | paper-toggle-button-unchecked-button-color: "#4284F4" 258 | paper-toggle-button-unchecked-bar-color: "#c1c1c1" 259 | ### Table row ### 260 | table-row-background-color: var(--primary-background-color) 261 | table-row-alternative-background-color: var(--secondary-background-color) 262 | 263 | iron-overlay-backdrop-background-color: "#ffffff" 264 | mdc-theme-primary: "#4284F4" -------------------------------------------------------------------------------- /themes/light-navy-blue.yaml: -------------------------------------------------------------------------------- 1 | Light - Navy Blue: 2 | ### Main Interface Colors ### 3 | primary-color: "#395274" 4 | light-primary-color: "#5F81B0" 5 | primary-background-color: "#F6F7F9" 6 | secondary-background-color: var(--primary-background-color) 7 | divider-color: "#D6DFEB" 8 | ### Text ### 9 | primary-text-color: "#395274" 10 | secondary-text-color: "#FF6262" 11 | text-primary-color: "#FFFFFF" 12 | disabled-text-color: "#88A1C4" 13 | ### Sidebar Menu ### 14 | sidebar-icon-color: "#395274" 15 | sidebar-text-color: var(--sidebar-icon-color) 16 | sidebar-selected-background-color: var(--primary-background-color) 17 | sidebar-selected-icon-color: "#FF6262" 18 | sidebar-selected-text-color: var(--sidebar-selected-icon-color) 19 | ### States and Badges ### 20 | state-icon-color: "#FF6262" 21 | state-icon-active-color: "#FBCD41" 22 | state-icon-unavailable-color: var(--disabled-text-color) 23 | ### Sliders ### 24 | paper-slider-knob-color: "#FF6262" 25 | paper-slider-knob-start-color: var(--paper-slider-knob-color) 26 | paper-slider-pin-color: var(--paper-slider-knob-color) 27 | paper-slider-active-color: var(--paper-slider-knob-color) 28 | paper-slider-secondary-color: var(--light-primary-color) 29 | ### Labels ### 30 | label-badge-background-color: "#FFFFFF" 31 | label-badge-text-color: "#395274" 32 | label-badge-red: "#FF8888" 33 | ### Cards ### 34 | paper-card-background-color: "#FFFFFF" 35 | paper-listbox-background-color: var(--primary-background-color) 36 | ### Toggles ### 37 | paper-toggle-button-checked-button-color: "#FF6262" 38 | paper-toggle-button-checked-bar-color: "#FFA3A3" 39 | paper-toggle-button-unchecked-button-color: "#FF6262" 40 | paper-toggle-button-unchecked-bar-color: "#9CB2CE" 41 | ### Table row ### 42 | table-row-background-color: var(--primary-background-color) 43 | table-row-alternative-background-color: var(--secondary-background-color) -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function get_file { 4 | DOWNLOAD_PATH=${2}?raw=true 5 | FILE_NAME=$1 6 | if [ "${FILE_NAME:0:1}" = "/" ]; then 7 | SAVE_PATH=$FILE_NAME 8 | else 9 | SAVE_PATH=$3$FILE_NAME 10 | fi 11 | TMP_NAME=${1}.tmp 12 | echo "Getting $1" 13 | # wget $DOWNLOAD_PATH -q -O $TMP_NAME 14 | curl -s -q -L -o $TMP_NAME $DOWNLOAD_PATH 15 | rv=$? 16 | if [ $rv != 0 ]; then 17 | rm $TMP_NAME 18 | echo "Download failed with error $rv" 19 | exit 20 | fi 21 | diff ${SAVE_PATH} $TMP_NAME &>/dev/null 22 | if [ $? == 0 ]; then 23 | echo "File up to date." 24 | rm $TMP_NAME 25 | return 0 26 | else 27 | mv $TMP_NAME ${SAVE_PATH} 28 | if [ $1 == $0 ]; then 29 | chmod u+x $0 30 | echo "Restarting" 31 | $0 32 | exit $? 33 | else 34 | return 1 35 | fi 36 | fi 37 | } 38 | 39 | function get_file_and_gz { 40 | get_file $1 $2 $3 41 | r1=$? 42 | get_file ${1}.gz ${2}.gz $3 43 | r2=$? 44 | if (( $r1 != 0 || $r2 != 0 )); then 45 | return 1 46 | fi 47 | return 0 48 | } 49 | 50 | function check_dir { 51 | if [ ! -d $1 ]; then 52 | read -p "$1 dir not found. Create? (y/n): [n] " r 53 | r=${r:-n} 54 | if [[ $r == 'y' || $r == 'Y' ]]; then 55 | mkdir -p $1 56 | else 57 | exit 58 | fi 59 | fi 60 | } 61 | 62 | if [ ! -f configuration.yaml ]; then 63 | echo "There is no configuration.yaml in current dir. 'update.sh' should run from Homeassistant config dir" 64 | read -p "Are you sure you want to continue? (y/n): [n] " r 65 | r=${r:-n} 66 | if [[ $r == 'n' || $r == 'N' ]]; then 67 | exit 68 | fi 69 | fi 70 | 71 | get_file $0 https://github.com/andrey-git/home-assistant-custom-ui/blob/master/update.sh ./ 72 | 73 | 74 | check_dir "www/custom_ui" 75 | 76 | 77 | get_file scripts.js.map https://github.com/andrey-git/home-assistant-custom-ui/blob/master/scripts.js.map www/custom_ui/ 78 | get_file scripts.js.LICENSE https://github.com/andrey-git/home-assistant-custom-ui/blob/master/scripts.js.LICENSE www/custom_ui/ 79 | get_file scripts-es5.js.map https://github.com/andrey-git/home-assistant-custom-ui/blob/master/scripts-es5.js.map www/custom_ui/ 80 | get_file scripts-es5.js.LICENSE https://github.com/andrey-git/home-assistant-custom-ui/blob/master/scripts-es5.js.LICENSE www/custom_ui/ 81 | get_file_and_gz state-card-custom-ui-es5.html https://github.com/andrey-git/home-assistant-custom-ui/blob/master/state-card-custom-ui-es5.html www/custom_ui/ 82 | get_file_and_gz state-card-custom-ui.html https://github.com/andrey-git/home-assistant-custom-ui/blob/master/state-card-custom-ui.html www/custom_ui/ 83 | 84 | 85 | if [ $? != 0 ]; then 86 | echo "Updated to Custom UI `grep -o -e '"[0-9][0-9][0-9]*"' www/custom_ui/state-card-custom-ui.html`" 87 | fi 88 | 89 | 90 | check_dir "custom_components/customizer" 91 | 92 | get_file __init__.py https://github.com/andrey-git/home-assistant-customizer/blob/master/customizer/__init__.py custom_components/customizer/ 93 | get_file services.yaml https://github.com/andrey-git/home-assistant-customizer/blob/master/customizer/services.yaml custom_components/customizer/ 94 | -------------------------------------------------------------------------------- /www/card-mod.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function n(i){if(t[i])return t[i].exports;var o=t[i]={i:i,l:!1,exports:{}};return e[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(i,o,function(t){return e[t]}.bind(null,o));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";function i(){return document.querySelector("home-assistant").hass}n.r(t);let o=function(){if(window.fully&&"function"==typeof fully.getDeviceId)return fully.getDeviceId();if(!localStorage["lovelace-player-device-id"]){const e=()=>Math.floor(1e5*(1+Math.random())).toString(16).substring(1);localStorage["lovelace-player-device-id"]=`${e()}${e()}-${e()}${e()}`}return localStorage["lovelace-player-device-id"]}();function a(e,t,n=null){if((e=new Event(e,{bubbles:!0,cancelable:!1,composed:!0})).detail=t||{},n)n.dispatchEvent(e);else{var i=document.querySelector("home-assistant");(i=(i=(i=(i=(i=(i=(i=(i=(i=(i=(i=i&&i.shadowRoot)&&i.querySelector("home-assistant-main"))&&i.shadowRoot)&&i.querySelector("app-drawer-layout partial-panel-resolver"))&&i.shadowRoot||i)&&i.querySelector("ha-panel-lovelace"))&&i.shadowRoot)&&i.querySelector("hui-root"))&&i.shadowRoot)&&i.querySelector("ha-app-layout #view"))&&i.firstElementChild)&&i.dispatchEvent(e)}}customElements.define("card-mod",class extends HTMLElement{disconnectedCallback(){this._disconnect()}connectedCallback(){this._connect()}_has_template(e){return!!e.template.includes("{%")||!!e.template.includes("{{")}set template(e){this._data=e,this._has_template(e)&&!this._data.entity_ids&&this._data.template.includes("config.entity")&&this._data.variables.config&&this._data.variables.config.entity&&(this._data.entity_ids=[this._data.variables.config.entity])}update(){this._disconnect().then(()=>this._connect())}async _connect(){this._data&&(this._has_template(this._data)||(this.innerHTML=``),this._unsubRenderTemplate||(this._unsubRenderTemplate=function(e,t,n){e||(e=i().connection);let a={user:i().user.name,browser:o,hash:location.hash.substr(1)||" ",...n.variables},s=n.template,r=n.entity_ids;return e.subscribeMessage(e=>t(e.result),{type:"render_template",template:s,variables:a,entity_ids:r})}(null,e=>this.innerHTML=``,this._data),this._unsubRenderTemplate.catch(()=>{this.innerHTML=``,this._unsubRenderTemplate=void 0})))}async _disconnect(){if(this._unsubRenderTemplate)try{const e=await this._unsubRenderTemplate;this._unsubRenderTemplate=void 0,await e()}catch(e){if("not_found"!==e.code)throw e}}});const s=async function(e,t,n,i){const o=function(e){i&&("string"==typeof e?console.log(" ".repeat(2*(i-1))+e):console.log(e))};if(e&&t)if(e.updateComplete&&await e.updateComplete,"string"==typeof t){const i=e.querySelector("card-mod");if(i)return void i.update();const a=document.createElement("card-mod");a.template={template:t,variables:n.variables,entity_ids:n.entity_ids},e.appendChild(a),o("Applied styles to:"),o(e)}else Object.keys(t).forEach(a=>"."===a?(o(`Stepping into root of ${e.tagName}`),s(e,t[a],n,i?i+1:0)):"$"===a?(o(`Stepping into ShadowRoot of ${e.tagName}`),s(e.shadowRoot,t[a],n,i?i+1:0)):(o(`Searching for: "${a}". ${e.querySelectorAll(a).length} matches.`),void e.querySelectorAll(`${a}`).forEach(e=>{o(`Stepping into ${e.tagName}`),s(e,t[a],n,i?i+1:0)})))};customElements.whenDefined("ha-card").then(()=>{const e=customElements.get("ha-card"),t=function(e){return e.config?e.config:e._config?e._config:e.host?t(e.host):e.parentElement?t(e.parentElement):e.parentNode?t(e.parentNode):null};e.prototype.firstUpdated=function(){const e=this.shadowRoot.querySelector(".card-header");e&&this.insertBefore(e,this.children[0]);const n=t(this);if(!n||!n.style)return;let i=n.entity_ids;const o=()=>{s(this,n.style,{variables:{config:n},entity_ids:i},!!n.debug_cardmod)};o(),window.addEventListener("location-changed",()=>o())},a("ll-rebuild",{})}),customElements.whenDefined("hui-entities-card").then(()=>{const e=customElements.get("hui-entities-card"),t=e.prototype.renderEntity;e.prototype.renderEntity=function(e){const n=t.bind(this)(e);if(!e||!e.style)return n;if(!n||!n.values)return n;const i=n.values[0];if(!i||!i.updateComplete)return n;let o=e.entity_ids;const a=()=>{s(i.shadowRoot,e.style,{variables:{config:e},entity_ids:o},!!e.debug_cardmod)};return i.updateComplete.then(a),window.addEventListener("location-changed",a),n},e.prototype._handleClick=function(e){switch(e.tap_action&&e.tap_action.action?e.tap_action.action:"more-info"){case"more-info":a("hass-more-info",{entityId:e.entity},this);break;case"navigate":history.pushState(null,"",e.tap_action.navigation_path),a("location-changed",{},this);break;case"url":e.tap_action.url_path&&window.open(e.tap_action.url_path);break;case"toggle":if(e.entity){const t=e.entity.split(".",1)[0],n=["closed","locked","off"].includes(this._hass.states[e.entity].state),i=({lock:["unlock","lock"],cover:["open_cover","close_cover"]}[t]||["turn_on","turn_off"])[n?0:1];this._hass.callService(t,i,{entity_id:e.entity})}break;case"call-service":{if(!e.tap_action.service)break;const[t,n]=e.tap_action.service.split(".",2);this._hass.callService(t,n,e.tap_action.service_data);break}}},a("ll-rebuild",{})}),customElements.whenDefined("hui-glance-card").then(()=>{customElements.get("hui-glance-card").prototype.firstUpdated=function(){this.shadowRoot.querySelectorAll("ha-card div.entity").forEach(e=>{const t=e.attachShadow({mode:"open"});[...e.children].forEach(e=>t.appendChild(e));const n=document.createElement("style");t.appendChild(n),n.innerHTML="\n :host {\n box-sizing: border-box;\n padding: 0 4px;\n display: flex;\n flex-direction: column;\n align-items: center;\n cursor: pointer;\n margin-bottom: 12px;\n width: var(--glance-column-width, 20%);\n }\n div {\n width: 100%;\n text-align: center;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .name {\n min-height: var(--paper-font-body1_-_line-height, 20px);\n }\n state-badge {\n margin: 8px 0;\n }\n ";const i=e.config||e.entityConf;if(!i||!i.style)return;let o=i.entity_ids;const a=()=>{s(t,i.style,{variables:{config:i},entity_ids:o},!!i.debug_cardmod)};a(),window.addEventListener("location-changed",a)})},a("ll-rebuild",{})})}]); -------------------------------------------------------------------------------- /www/custom_ui/scripts-es5.js.LICENSE: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 4 | * This code may only be used under the BSD style license found at 5 | * http://polymer.github.io/LICENSE.txt 6 | * The complete set of authors may be found at 7 | * http://polymer.github.io/AUTHORS.txt 8 | * The complete set of contributors may be found at 9 | * http://polymer.github.io/CONTRIBUTORS.txt 10 | * Code distributed by Google as part of the polymer project is also 11 | * subject to an additional IP rights grant found at 12 | * http://polymer.github.io/PATENTS.txt 13 | */ 14 | 15 | /** 16 | * @license 17 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 18 | * This code may only be used under the BSD style license found at 19 | * http://polymer.github.io/LICENSE.txt 20 | * The complete set of authors may be found at 21 | * http://polymer.github.io/AUTHORS.txt 22 | * The complete set of contributors may be found at 23 | * http://polymer.github.io/CONTRIBUTORS.txt 24 | * Code distributed by Google as part of the polymer project is also 25 | * subject to an additional IP rights grant found at 26 | * http://polymer.github.io/PATENTS.txt 27 | */ 28 | 29 | /** 30 | * @license 31 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 32 | * This code may only be used under the BSD style license found at 33 | * http://polymer.github.io/LICENSE.txt 34 | * The complete set of authors may be found at 35 | * http://polymer.github.io/AUTHORS.txt 36 | * The complete set of contributors may be found at 37 | * http://polymer.github.io/CONTRIBUTORS.txt 38 | * Code distributed by Google as part of the polymer project is also 39 | * subject to an additional IP rights grant found at 40 | * http://polymer.github.io/PATENTS.txt 41 | */ 42 | 43 | /** 44 | * @license 45 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 46 | * This code may only be used under the BSD style license found at 47 | * http://polymer.github.io/LICENSE.txt 48 | * The complete set of authors may be found at 49 | * http://polymer.github.io/AUTHORS.txt 50 | * The complete set of contributors may be found at 51 | * http://polymer.github.io/CONTRIBUTORS.txt 52 | * Code distributed by Google as part of the polymer project is also 53 | * subject to an additional IP rights grant found at 54 | * http://polymer.github.io/PATENTS.txt 55 | */ 56 | 57 | /** 58 | * @license 59 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 60 | * This code may only be used under the BSD style license found at 61 | * http://polymer.github.io/LICENSE.txt 62 | * The complete set of authors may be found at 63 | * http://polymer.github.io/AUTHORS.txt 64 | * The complete set of contributors may be found at 65 | * http://polymer.github.io/CONTRIBUTORS.txt 66 | * Code distributed by Google as part of the polymer project is also 67 | * subject to an additional IP rights grant found at 68 | * http://polymer.github.io/PATENTS.txt 69 | */ 70 | 71 | /** 72 | * @license 73 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 74 | * This code may only be used under the BSD style license found at 75 | * http://polymer.github.io/LICENSE.txt 76 | * The complete set of authors may be found at 77 | * http://polymer.github.io/AUTHORS.txt 78 | * The complete set of contributors may be found at 79 | * http://polymer.github.io/CONTRIBUTORS.txt 80 | * Code distributed by Google as part of the polymer project is also 81 | * subject to an additional IP rights grant found at 82 | * http://polymer.github.io/PATENTS.txt 83 | */ 84 | 85 | /** 86 | * @license 87 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 88 | * This code may only be used under the BSD style license found at 89 | * http://polymer.github.io/LICENSE.txt 90 | * The complete set of authors may be found at 91 | * http://polymer.github.io/AUTHORS.txt 92 | * The complete set of contributors may be found at 93 | * http://polymer.github.io/CONTRIBUTORS.txt 94 | * Code distributed by Google as part of the polymer project is also 95 | * subject to an additional IP rights grant found at 96 | * http://polymer.github.io/PATENTS.txt 97 | */ 98 | 99 | /** 100 | * @license 101 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 102 | * This code may only be used under the BSD style license found at 103 | * http://polymer.github.io/LICENSE.txt 104 | * The complete set of authors may be found at 105 | * http://polymer.github.io/AUTHORS.txt 106 | * The complete set of contributors may be found at 107 | * http://polymer.github.io/CONTRIBUTORS.txt 108 | * Code distributed by Google as part of the polymer project is also 109 | * subject to an additional IP rights grant found at 110 | * http://polymer.github.io/PATENTS.txt 111 | */ 112 | 113 | /** 114 | * @license 115 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 116 | * This code may only be used under the BSD style license found at 117 | * http://polymer.github.io/LICENSE.txt 118 | * The complete set of authors may be found at 119 | * http://polymer.github.io/AUTHORS.txt 120 | * The complete set of contributors may be found at 121 | * http://polymer.github.io/CONTRIBUTORS.txt 122 | * Code distributed by Google as part of the polymer project is also 123 | * subject to an additional IP rights grant found at 124 | * http://polymer.github.io/PATENTS.txt 125 | */ 126 | 127 | /** 128 | * @license 129 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 130 | * This code may only be used under the BSD style license found at 131 | * http://polymer.github.io/LICENSE.txt 132 | * The complete set of authors may be found at 133 | * http://polymer.github.io/AUTHORS.txt 134 | * The complete set of contributors may be found at 135 | * http://polymer.github.io/CONTRIBUTORS.txt 136 | * Code distributed by Google as part of the polymer project is also 137 | * subject to an additional IP rights grant found at 138 | * http://polymer.github.io/PATENTS.txt 139 | */ 140 | 141 | /** 142 | * @license 143 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 144 | * This code may only be used under the BSD style license found at 145 | * http://polymer.github.io/LICENSE.txt 146 | * The complete set of authors may be found at 147 | * http://polymer.github.io/AUTHORS.txt 148 | * The complete set of contributors may be found at 149 | * http://polymer.github.io/CONTRIBUTORS.txt 150 | * Code distributed by Google as part of the polymer project is also 151 | * subject to an additional IP rights grant found at 152 | * http://polymer.github.io/PATENTS.txt 153 | */ 154 | 155 | /** 156 | @license 157 | Copyright (c) 2019 The Polymer Project Authors. All rights reserved. 158 | This code may only be used under the BSD style license found at 159 | http://polymer.github.io/LICENSE.txt The complete set of authors may be found at 160 | http://polymer.github.io/AUTHORS.txt The complete set of contributors may be 161 | found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as 162 | part of the polymer project is also subject to an additional IP rights grant 163 | found at http://polymer.github.io/PATENTS.txt 164 | */ 165 | 166 | /** 167 | * @license 168 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 169 | * This code may only be used under the BSD style license found at 170 | * http://polymer.github.io/LICENSE.txt 171 | * The complete set of authors may be found at 172 | * http://polymer.github.io/AUTHORS.txt 173 | * The complete set of contributors may be found at 174 | * http://polymer.github.io/CONTRIBUTORS.txt 175 | * Code distributed by Google as part of the polymer project is also 176 | * subject to an additional IP rights grant found at 177 | * http://polymer.github.io/PATENTS.txt 178 | */ 179 | 180 | /** 181 | * @license 182 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 183 | * This code may only be used under the BSD style license found at 184 | * http://polymer.github.io/LICENSE.txt 185 | * The complete set of authors may be found at 186 | * http://polymer.github.io/AUTHORS.txt 187 | * The complete set of contributors may be found at 188 | * http://polymer.github.io/CONTRIBUTORS.txt 189 | * Code distributed by Google as part of the polymer project is also 190 | * subject to an additional IP rights grant found at 191 | * http://polymer.github.io/PATENTS.txt 192 | */ 193 | 194 | /** 195 | @license 196 | Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 197 | This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 198 | The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 199 | The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 200 | Code distributed by Google as part of the polymer project is also 201 | subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 202 | */ 203 | 204 | /** 205 | @license 206 | Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 207 | This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 208 | The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 209 | The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 210 | Code distributed by Google as part of the polymer project is also 211 | subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 212 | */ 213 | -------------------------------------------------------------------------------- /www/custom_ui/scripts.js.LICENSE: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 4 | * This code may only be used under the BSD style license found at 5 | * http://polymer.github.io/LICENSE.txt 6 | * The complete set of authors may be found at 7 | * http://polymer.github.io/AUTHORS.txt 8 | * The complete set of contributors may be found at 9 | * http://polymer.github.io/CONTRIBUTORS.txt 10 | * Code distributed by Google as part of the polymer project is also 11 | * subject to an additional IP rights grant found at 12 | * http://polymer.github.io/PATENTS.txt 13 | */ 14 | 15 | /** 16 | * @license 17 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 18 | * This code may only be used under the BSD style license found at 19 | * http://polymer.github.io/LICENSE.txt 20 | * The complete set of authors may be found at 21 | * http://polymer.github.io/AUTHORS.txt 22 | * The complete set of contributors may be found at 23 | * http://polymer.github.io/CONTRIBUTORS.txt 24 | * Code distributed by Google as part of the polymer project is also 25 | * subject to an additional IP rights grant found at 26 | * http://polymer.github.io/PATENTS.txt 27 | */ 28 | 29 | /** 30 | * @license 31 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 32 | * This code may only be used under the BSD style license found at 33 | * http://polymer.github.io/LICENSE.txt 34 | * The complete set of authors may be found at 35 | * http://polymer.github.io/AUTHORS.txt 36 | * The complete set of contributors may be found at 37 | * http://polymer.github.io/CONTRIBUTORS.txt 38 | * Code distributed by Google as part of the polymer project is also 39 | * subject to an additional IP rights grant found at 40 | * http://polymer.github.io/PATENTS.txt 41 | */ 42 | 43 | /** 44 | * @license 45 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 46 | * This code may only be used under the BSD style license found at 47 | * http://polymer.github.io/LICENSE.txt 48 | * The complete set of authors may be found at 49 | * http://polymer.github.io/AUTHORS.txt 50 | * The complete set of contributors may be found at 51 | * http://polymer.github.io/CONTRIBUTORS.txt 52 | * Code distributed by Google as part of the polymer project is also 53 | * subject to an additional IP rights grant found at 54 | * http://polymer.github.io/PATENTS.txt 55 | */ 56 | 57 | /** 58 | * @license 59 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 60 | * This code may only be used under the BSD style license found at 61 | * http://polymer.github.io/LICENSE.txt 62 | * The complete set of authors may be found at 63 | * http://polymer.github.io/AUTHORS.txt 64 | * The complete set of contributors may be found at 65 | * http://polymer.github.io/CONTRIBUTORS.txt 66 | * Code distributed by Google as part of the polymer project is also 67 | * subject to an additional IP rights grant found at 68 | * http://polymer.github.io/PATENTS.txt 69 | */ 70 | 71 | /** 72 | * @license 73 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 74 | * This code may only be used under the BSD style license found at 75 | * http://polymer.github.io/LICENSE.txt 76 | * The complete set of authors may be found at 77 | * http://polymer.github.io/AUTHORS.txt 78 | * The complete set of contributors may be found at 79 | * http://polymer.github.io/CONTRIBUTORS.txt 80 | * Code distributed by Google as part of the polymer project is also 81 | * subject to an additional IP rights grant found at 82 | * http://polymer.github.io/PATENTS.txt 83 | */ 84 | 85 | /** 86 | * @license 87 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 88 | * This code may only be used under the BSD style license found at 89 | * http://polymer.github.io/LICENSE.txt 90 | * The complete set of authors may be found at 91 | * http://polymer.github.io/AUTHORS.txt 92 | * The complete set of contributors may be found at 93 | * http://polymer.github.io/CONTRIBUTORS.txt 94 | * Code distributed by Google as part of the polymer project is also 95 | * subject to an additional IP rights grant found at 96 | * http://polymer.github.io/PATENTS.txt 97 | */ 98 | 99 | /** 100 | * @license 101 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 102 | * This code may only be used under the BSD style license found at 103 | * http://polymer.github.io/LICENSE.txt 104 | * The complete set of authors may be found at 105 | * http://polymer.github.io/AUTHORS.txt 106 | * The complete set of contributors may be found at 107 | * http://polymer.github.io/CONTRIBUTORS.txt 108 | * Code distributed by Google as part of the polymer project is also 109 | * subject to an additional IP rights grant found at 110 | * http://polymer.github.io/PATENTS.txt 111 | */ 112 | 113 | /** 114 | * @license 115 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 116 | * This code may only be used under the BSD style license found at 117 | * http://polymer.github.io/LICENSE.txt 118 | * The complete set of authors may be found at 119 | * http://polymer.github.io/AUTHORS.txt 120 | * The complete set of contributors may be found at 121 | * http://polymer.github.io/CONTRIBUTORS.txt 122 | * Code distributed by Google as part of the polymer project is also 123 | * subject to an additional IP rights grant found at 124 | * http://polymer.github.io/PATENTS.txt 125 | */ 126 | 127 | /** 128 | * @license 129 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 130 | * This code may only be used under the BSD style license found at 131 | * http://polymer.github.io/LICENSE.txt 132 | * The complete set of authors may be found at 133 | * http://polymer.github.io/AUTHORS.txt 134 | * The complete set of contributors may be found at 135 | * http://polymer.github.io/CONTRIBUTORS.txt 136 | * Code distributed by Google as part of the polymer project is also 137 | * subject to an additional IP rights grant found at 138 | * http://polymer.github.io/PATENTS.txt 139 | */ 140 | 141 | /** 142 | @license 143 | Copyright (c) 2019 The Polymer Project Authors. All rights reserved. 144 | This code may only be used under the BSD style license found at 145 | http://polymer.github.io/LICENSE.txt The complete set of authors may be found at 146 | http://polymer.github.io/AUTHORS.txt The complete set of contributors may be 147 | found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as 148 | part of the polymer project is also subject to an additional IP rights grant 149 | found at http://polymer.github.io/PATENTS.txt 150 | */ 151 | 152 | /** 153 | * @license 154 | * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 155 | * This code may only be used under the BSD style license found at 156 | * http://polymer.github.io/LICENSE.txt 157 | * The complete set of authors may be found at 158 | * http://polymer.github.io/AUTHORS.txt 159 | * The complete set of contributors may be found at 160 | * http://polymer.github.io/CONTRIBUTORS.txt 161 | * Code distributed by Google as part of the polymer project is also 162 | * subject to an additional IP rights grant found at 163 | * http://polymer.github.io/PATENTS.txt 164 | */ 165 | 166 | /** 167 | @license 168 | Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 169 | This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 170 | The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 171 | The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 172 | Code distributed by Google as part of the polymer project is also 173 | subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 174 | */ 175 | 176 | /** 177 | @license 178 | Copyright (c) 2017 The Polymer Project Authors. All rights reserved. 179 | This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt 180 | The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 181 | The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt 182 | Code distributed by Google as part of the polymer project is also 183 | subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt 184 | */ 185 | -------------------------------------------------------------------------------- /www/custom_ui/state-card-custom-ui-es5.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /www/custom_ui/state-card-custom-ui-es5.html.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaneclaes/van-home-assistant-config/907196e279a1f9bccc25649bf42c1c99773e50c1/www/custom_ui/state-card-custom-ui-es5.html.gz -------------------------------------------------------------------------------- /www/custom_ui/state-card-custom-ui.html: -------------------------------------------------------------------------------- 1 | 242 | -------------------------------------------------------------------------------- /www/custom_ui/state-card-custom-ui.html.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaneclaes/van-home-assistant-config/907196e279a1f9bccc25649bf42c1c99773e50c1/www/custom_ui/state-card-custom-ui.html.gz -------------------------------------------------------------------------------- /www/kiosk.css: -------------------------------------------------------------------------------- 1 | #view { 2 | min-height: 110vh !important; 3 | } -------------------------------------------------------------------------------- /www/kiosk.js: -------------------------------------------------------------------------------- 1 | // Adapted from https://gist.github.com/ciotlosm/1f09b330aa5bd5ea87b59f33609cc931 2 | if (window.location.href.indexOf('kiosk') > 0) { 3 | setTimeout(function () { 4 | try { 5 | const home_assistant_main = document 6 | .querySelector("body > home-assistant").shadowRoot 7 | .querySelector("home-assistant-main"); 8 | 9 | var header = home_assistant_main.shadowRoot 10 | .querySelector("app-drawer-layout > partial-panel-resolver > ha-panel-lovelace").shadowRoot 11 | .querySelector("hui-root").shadowRoot 12 | .querySelector('#layout > app-header') 13 | if (window.location.href.indexOf('show_tabs') > 0) { 14 | header = header.querySelector('app-toolbar') 15 | } 16 | 17 | const drawer = home_assistant_main.shadowRoot.querySelector("#drawer"); 18 | 19 | header.style.display = "none"; 20 | drawer.style.display = 'none'; 21 | 22 | home_assistant_main.style.setProperty("--app-drawer-width", 0); 23 | home_assistant_main.shadowRoot 24 | .querySelector("#drawer > ha-sidebar").shadowRoot 25 | .querySelector("div.menu > paper-icon-button") 26 | .click(); 27 | 28 | window.dispatchEvent(new Event('resize')); 29 | } 30 | catch (e) { 31 | console.log(e); 32 | } 33 | }, 200); 34 | } -------------------------------------------------------------------------------- /www/monster-card.js: -------------------------------------------------------------------------------- 1 | class MonsterCard extends HTMLElement { 2 | 3 | _getEntities(hass, filters) { 4 | function _filterEntityId(stateObj, pattern) { 5 | if (pattern.indexOf('*') === -1) { 6 | return stateObj.entity_id === pattern; 7 | } 8 | const regEx = new RegExp(`^${pattern.replace(/\*/g, '.*')}$`, 'i'); 9 | return stateObj.entity_id.search(regEx) === 0; 10 | } 11 | function _filterName(stateObj, pattern) { 12 | let compareEntity = stateObj.attributes.title ? stateObj.attributes.title : stateObj.attributes.friendly_name; 13 | if (!compareEntity) compareEntity = stateObj.entity_id; 14 | if (pattern.indexOf('*') === -1) { 15 | return compareEntity === pattern; 16 | } 17 | const regEx = new RegExp(`^${pattern.replace(/\*/g, '.*')}$`, 'i'); 18 | return compareEntity.search(regEx) === 0; 19 | } 20 | // Allows '< 300' in b 21 | function _complexCompare(a, b) { 22 | const _compare = { 23 | '>': (x, y) => x > y, 24 | '<': (x, y) => x < y, 25 | '<=': (x, y) => x <= y, 26 | '>=': (x, y) => x >= y, 27 | '=': (x, y) => x === y, 28 | }; 29 | let operator = '='; 30 | let y = b; 31 | let x = a; 32 | if (!isNaN(a) && typeof (b) == 'string' 33 | && b.split(" ").length > 1) { 34 | [operator, y] = b.split(' ', 2); 35 | x = parseFloat(a); 36 | } 37 | return _compare[operator](x, y); 38 | } 39 | const entities = new Map(); 40 | filters.forEach((filter) => { 41 | const filters = []; 42 | if (filter.domain) { 43 | filters.push(stateObj => stateObj.entity_id.split('.', 1)[0] === filter.domain); 44 | } 45 | if (filter.attributes) { 46 | Object.keys(filter.attributes).forEach(key => { 47 | filters.push(stateObj => _complexCompare(stateObj.attributes[key], filter.attributes[key])); 48 | }); 49 | } 50 | if (filter.entity_id) { 51 | filters.push(stateObj => _filterEntityId(stateObj, filter.entity_id)); 52 | } 53 | if (filter.name) { 54 | filters.push(stateObj => _filterName(stateObj, filter.name)); 55 | } 56 | if (filter.state) { 57 | filters.push(stateObj => _complexCompare(stateObj.state, filter.state)); 58 | } 59 | 60 | const options = filter.options ? filter.options : {} 61 | 62 | Object.keys(hass.states).sort().forEach(key => { 63 | if (filters.every(filterFunc => filterFunc(hass.states[key]))) { 64 | const dynOptions = JSON.parse(JSON.stringify(options).replace(/this.entity_id/g,hass.states[key].entity_id)); 65 | entities.set(hass.states[key].entity_id, Object.assign({ "entity": hass.states[key].entity_id }, dynOptions)); 66 | } 67 | }); 68 | }); 69 | return Array.from(entities.values()); 70 | } 71 | 72 | setConfig(config) { 73 | if (!config.filter.include || !Array.isArray(config.filter.include)) { 74 | throw new Error('Please define filters'); 75 | } 76 | 77 | if (this.lastChild) this.removeChild(this.lastChild); 78 | 79 | const cardConfig = Object.assign({}, config); 80 | if (!cardConfig.card) cardConfig.card = {}; 81 | if (config.card.entities) delete config.card.entities; 82 | if (!cardConfig.card.type) cardConfig.card.type = 'entities'; 83 | 84 | const element = document.createElement(`hui-${cardConfig.card.type}-card`); 85 | this.appendChild(element); 86 | 87 | this._config = cardConfig; 88 | } 89 | 90 | set hass(hass) { 91 | const config = this._config; 92 | let entities = this._getEntities(hass, config.filter.include); 93 | if (config.filter.exclude) { 94 | const excludeEntities = this._getEntities(hass, config.filter.exclude).map(entity => entity.entity); 95 | entities = entities.filter(entity => !excludeEntities.includes(entity.entity)); 96 | } 97 | 98 | 99 | 100 | if (entities.length === 0 && config.show_empty === false) { 101 | this.style.display = 'none'; 102 | } else { 103 | if (config.when && (hass.states[config.when.entity].state == config.when.state) || !config.when) { 104 | this.style.display = 'block'; 105 | } else { 106 | this.style.display = 'none'; 107 | } 108 | } 109 | 110 | if (!config.card.entities || config.card.entities.length !== entities.length || 111 | !config.card.entities.every((value, index) => value.entity === entities[index].entity)) { 112 | config.card.entities = entities; 113 | this.lastChild.setConfig(config.card); 114 | } 115 | this.lastChild.hass = hass; 116 | } 117 | 118 | getCardSize() { 119 | return 'getCardSize' in this.lastChild ? this.lastChild.getCardSize() : 1; 120 | } 121 | } 122 | 123 | customElements.define('monster-card', MonsterCard); 124 | -------------------------------------------------------------------------------- /www/photos/van-overhead.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaneclaes/van-home-assistant-config/907196e279a1f9bccc25649bf42c1c99773e50c1/www/photos/van-overhead.jpg -------------------------------------------------------------------------------- /www/photos/van-side.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zaneclaes/van-home-assistant-config/907196e279a1f9bccc25649bf42c1c99773e50c1/www/photos/van-side.jpg --------------------------------------------------------------------------------