diff --git a/README.md b/README.md index 0ff914c3..50105a87 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Build Status](https://github.com/aneisch/home-assistant-config/actions/workflows/check-ha-release-compatibility.yml/badge.svg)](https://github.com/aneisch/home-assistant-config/actions) [![GitHub last commit](https://img.shields.io/github/last-commit/aneisch/home-assistant-config)](https://github.com/aneisch/home-assistant-config/commits/master) [![GitHub commit activity](https://img.shields.io/github/commit-activity/y/aneisch/home-assistant-config)](https://github.com/aneisch/home-assistant-config/graphs/commit-activity) -[![HA Version](https://img.shields.io/badge/Running%20Home%20Assistant-2024.9.3%20(Latest)-brightgreen)](https://github.com/home-assistant/home-assistant/releases/latest) +[![HA Version](https://img.shields.io/badge/Running%20Home%20Assistant-2024.10.1%20(Latest)-brightgreen)](https://github.com/home-assistant/home-assistant/releases/latest)
Buy Me A Coffee I do my best to keep [Home Assistant](https://github.com/home-assistant/home-assistant) on the [latest release](https://github.com/home-assistant/home-assistant/releases/latest). I'm heavily utilizing [AppDaemon](http://appdaemon.readthedocs.io/en/latest/) and [NodeRed](https://flows.nodered.org/node/node-red-contrib-home-assistant-websocket) for advanced/templated automations. See [Appdaemon config](https://github.com/aneisch/home-assistant-config/tree/master/extras/appdaemon) and my NodeRed screenshots below for details. Most of my setup is run as Docker containers (see [docker-compose](https://github.com/aneisch/home-assistant-config/tree/master/extras/docker-compose) for container list). @@ -58,19 +58,19 @@ Home Assistant and other containers have ingress handled automatically by [Traef ## Some statistics about my installation: Description | value -- | -- -Lines of ESPHome YAML | 3250 -Lines of Home Assistant YAML | 9707 +Lines of ESPHome YAML | 3246 +Lines of Home Assistant YAML | 10611 [Integrations](https://www.home-assistant.io/integrations/) in use | 64 Zigbee devices in [`zha`](https://www.home-assistant.io/integrations/zha/) | 26 Z-Wave devices in [`zwave_js`](https://www.home-assistant.io/integrations/zwave_js/) | 37 Description | value -- | -- -Entities in the [`automation`](https://www.home-assistant.io/components/automation) domain | 130 -Entities in the [`binary_sensor`](https://www.home-assistant.io/components/binary_sensor) domain | 162 -Entities in the [`button`](https://www.home-assistant.io/components/button) domain | 48 +Entities in the [`automation`](https://www.home-assistant.io/components/automation) domain | 134 +Entities in the [`binary_sensor`](https://www.home-assistant.io/components/binary_sensor) domain | 170 +Entities in the [`button`](https://www.home-assistant.io/components/button) domain | 46 Entities in the [`camera`](https://www.home-assistant.io/components/camera) domain | 16 -Entities in the [`climate`](https://www.home-assistant.io/components/climate) domain | 2 +Entities in the [`climate`](https://www.home-assistant.io/components/climate) domain | 1 Entities in the [`conversation`](https://www.home-assistant.io/components/conversation) domain | 2 Entities in the [`counter`](https://www.home-assistant.io/components/counter) domain | 1 Entities in the [`cover`](https://www.home-assistant.io/components/cover) domain | 16 @@ -84,9 +84,9 @@ Entities in the [`input_boolean`](https://www.home-assistant.io/components/input Entities in the [`input_datetime`](https://www.home-assistant.io/components/input_datetime) domain | 33 Entities in the [`input_number`](https://www.home-assistant.io/components/input_number) domain | 6 Entities in the [`input_select`](https://www.home-assistant.io/components/input_select) domain | 19 -Entities in the [`input_text`](https://www.home-assistant.io/components/input_text) domain | 16 +Entities in the [`input_text`](https://www.home-assistant.io/components/input_text) domain | 17 Entities in the [`light`](https://www.home-assistant.io/components/light) domain | 39 -Entities in the [`lock`](https://www.home-assistant.io/components/lock) domain | 5 +Entities in the [`lock`](https://www.home-assistant.io/components/lock) domain | 4 Entities in the [`media_player`](https://www.home-assistant.io/components/media_player) domain | 19 Entities in the [`notify`](https://www.home-assistant.io/components/notify) domain | 2 Entities in the [`number`](https://www.home-assistant.io/components/number) domain | 16 @@ -94,19 +94,19 @@ Entities in the [`person`](https://www.home-assistant.io/components/person) doma Entities in the [`plant`](https://www.home-assistant.io/components/plant) domain | 1 Entities in the [`remote`](https://www.home-assistant.io/components/remote) domain | 4 Entities in the [`script`](https://www.home-assistant.io/components/script) domain | 52 -Entities in the [`select`](https://www.home-assistant.io/components/select) domain | 8 -Entities in the [`sensor`](https://www.home-assistant.io/components/sensor) domain | 543 +Entities in the [`select`](https://www.home-assistant.io/components/select) domain | 4 +Entities in the [`sensor`](https://www.home-assistant.io/components/sensor) domain | 562 Entities in the [`setter`](https://www.home-assistant.io/components/setter) domain | 1 Entities in the [`siren`](https://www.home-assistant.io/components/siren) domain | 1 Entities in the [`sun`](https://www.home-assistant.io/components/sun) domain | 1 -Entities in the [`switch`](https://www.home-assistant.io/components/switch) domain | 189 -Entities in the [`timer`](https://www.home-assistant.io/components/timer) domain | 6 +Entities in the [`switch`](https://www.home-assistant.io/components/switch) domain | 191 +Entities in the [`timer`](https://www.home-assistant.io/components/timer) domain | 7 Entities in the [`tts`](https://www.home-assistant.io/components/tts) domain | 1 -Entities in the [`update`](https://www.home-assistant.io/components/update) domain | 84 +Entities in the [`update`](https://www.home-assistant.io/components/update) domain | 83 Entities in the [`vacuum`](https://www.home-assistant.io/components/vacuum) domain | 1 Entities in the [`weather`](https://www.home-assistant.io/components/weather) domain | 1 -Entities in the [`zone`](https://www.home-assistant.io/components/zone) domain | 6 -**Total state objects** | **1520** +Entities in the [`zone`](https://www.home-assistant.io/components/zone) domain | 7 +**Total state objects** | **1547** ## The HACS integrations/plugins that I use: **Appdaemon**:
diff --git a/automations.yaml b/automations.yaml index 518ff3ce..df377168 100644 --- a/automations.yaml +++ b/automations.yaml @@ -638,21 +638,23 @@ action: - action: homeassistant.turn_on entity_id: switch.docker_watchtower -- alias: Update Utility Costs - id: update_utility_costs - mode: single +- id: update_utility_costs + alias: Update Utility Costs trigger: - platform: time_pattern hours: /12 - platform: time at: '23:59:30' action: - - action: python_script.compute_utility_costs - data: - meter_entity: sensor.electricity_usage - action: python_script.compute_utility_costs data: meter_entity: sensor.water_usage + alias: Water + - alias: Electricity + action: python_script.compute_utility_costs + data: + meter_entity: sensor.electricity_usage + mode: single - id: reset_utility_meters alias: Reset Utility Meters trigger: @@ -1248,19 +1250,3 @@ ' mode: single -- id: '1727469189792' - alias: Total Power Alert - description: '' - trigger: - - platform: numeric_state - entity_id: - - sensor.total_power - above: 18000 - condition: [] - action: - - action: script.notify_wrapper - data: - message: Total power has exceeded 18k Watts! Currently {{trigger.to_state.state}} - data: - priority: 1 - mode: single diff --git a/configuration.yaml b/configuration.yaml index 7b7cd1b8..74f2970a 100644 --- a/configuration.yaml +++ b/configuration.yaml @@ -29,6 +29,7 @@ homeassistant: leak_detection: !include packages/leak_detection.yaml reminders: !include packages/reminders.yaml photo_frames: !include packages/photo_frames.yaml + tesla: !include packages/tesla.yaml timers: !include packages/timers.yaml ups_monitoring: !include packages/ups_monitor.yaml vacuum: !include packages/vacuum.yaml @@ -369,12 +370,6 @@ notify: # api_key: !secret pushbullet_key # name: pushbullet - - platform: html5 - name: html5 - vapid_pub_key: !secret vapid_pub_key - vapid_prv_key: !secret vapid_prv_key - vapid_email: !secret vapid_email - - platform: signal_messenger name: signal_self url: "http://localhost:8800" # the URL where the Signal Messenger REST API is listening diff --git a/extras/docker-compose/other/docker-compose.yml b/extras/docker-compose/other/docker-compose.yml index 4a979562..710c0928 100644 --- a/extras/docker-compose/other/docker-compose.yml +++ b/extras/docker-compose/other/docker-compose.yml @@ -833,6 +833,65 @@ services: - traefik.http.middlewares.add-guacamole.addPrefix.prefix=/guacamole - traefik.http.routers.guacamole_local.service=guacamole + teslamate: + image: teslamate/teslamate:latest + container_name: teslamate + restart: always + environment: + - ENCRYPTION_KEY=PW #replace with a secure key to encrypt your Tesla API tokens + - DATABASE_USER=teslamate + - DATABASE_PASS=PW #insert your secure database password! + - DATABASE_NAME=teslamate + - DATABASE_HOST=teslamate-database + - MQTT_HOST=mosquitto + - TZ=America/Chicago + ports: + - 4001:4000 + volumes: + - /opt/teslamate/teslamate:/opt/app/import + cap_drop: + - all + + teslamate-database: + image: postgres:16 + container_name: teslamate-database + restart: always + environment: + - POSTGRES_USER=teslamate + - POSTGRES_PASSWORD=PW #insert your secure database password! + - POSTGRES_DB=teslamate + volumes: + - /opt/teslamate/db:/var/lib/postgresql/data + + teslamate-grafana: + image: teslamate/grafana:latest + container_name: teslamate-grafana + restart: always + environment: + - DATABASE_USER=teslamate + - DATABASE_PASS=password #insert your secure database password! + - DATABASE_NAME=teslamate + - DATABASE_HOST=database + # ports: + # - 3001:3000 + volumes: + - /opt/teslamate/grafana:/var/lib/grafana + labels: + - traefik.enable=true + - traefik.http.services.teslamate.loadbalancer.server.port=3000 + # HTTPS for CF + # - traefik.http.routers.teslamate.entrypoints=websecure + # - traefik.http.routers.teslamate.tls=true + # - traefik.http.routers.teslamate.rule=Host(`teslamate.domain.com`) + # - traefik.http.routers.teslamate.service=teslamate + # HTTPS Local Only (with 80-->443 redirect) + - traefik.http.routers.teslamate_local.tls=true + - traefik.http.routers.teslamate_local.tls.certResolver=le-home + - traefik.http.routers.teslamate_local.tls.domains[0].main=*.home.domain.com + - traefik.http.routers.teslamate_local.rule=Host(`teslamate.home.domain.com`) + - traefik.http.routers.teslamate_local.service=teslamate + + # networks: # macos_network: # driver: bridge diff --git a/extras/docker-compose/unified/docker-compose.yml b/extras/docker-compose/unified/docker-compose.yml index 3cd30a50..fce434f0 100644 --- a/extras/docker-compose/unified/docker-compose.yml +++ b/extras/docker-compose/unified/docker-compose.yml @@ -1048,6 +1048,65 @@ services: - traefik.http.middlewares.add-guacamole.addPrefix.prefix=/guacamole - traefik.http.routers.guacamole_local.service=guacamole + teslamate: + image: teslamate/teslamate:latest + container_name: teslamate + restart: always + environment: + - ENCRYPTION_KEY=PW #replace with a secure key to encrypt your Tesla API tokens + - DATABASE_USER=teslamate + - DATABASE_PASS=PW #insert your secure database password! + - DATABASE_NAME=teslamate + - DATABASE_HOST=teslamate-database + - MQTT_HOST=mosquitto + - TZ=America/Chicago + ports: + - 4001:4000 + volumes: + - /opt/teslamate/teslamate:/opt/app/import + cap_drop: + - all + + teslamate-database: + image: postgres:16 + container_name: teslamate-database + restart: always + environment: + - POSTGRES_USER=teslamate + - POSTGRES_PASSWORD=PW #insert your secure database password! + - POSTGRES_DB=teslamate + volumes: + - /opt/teslamate/db:/var/lib/postgresql/data + + teslamate-grafana: + image: teslamate/grafana:latest + container_name: teslamate-grafana + restart: always + environment: + - DATABASE_USER=teslamate + - DATABASE_PASS=password #insert your secure database password! + - DATABASE_NAME=teslamate + - DATABASE_HOST=database + # ports: + # - 3001:3000 + volumes: + - /opt/teslamate/grafana:/var/lib/grafana + labels: + - traefik.enable=true + - traefik.http.services.teslamate.loadbalancer.server.port=3000 + # HTTPS for CF + # - traefik.http.routers.teslamate.entrypoints=websecure + # - traefik.http.routers.teslamate.tls=true + # - traefik.http.routers.teslamate.rule=Host(`teslamate.domain.com`) + # - traefik.http.routers.teslamate.service=teslamate + # HTTPS Local Only (with 80-->443 redirect) + - traefik.http.routers.teslamate_local.tls=true + - traefik.http.routers.teslamate_local.tls.certResolver=le-home + - traefik.http.routers.teslamate_local.tls.domains[0].main=*.home.domain.com + - traefik.http.routers.teslamate_local.rule=Host(`teslamate.home.domain.com`) + - traefik.http.routers.teslamate_local.service=teslamate + + # networks: # macos_network: # driver: bridge diff --git a/extras/esphome/mom_and_dad_gate.yaml b/extras/esphome/mom_and_dad_gate.yaml index 0170fec5..39d55759 100644 --- a/extras/esphome/mom_and_dad_gate.yaml +++ b/extras/esphome/mom_and_dad_gate.yaml @@ -15,9 +15,6 @@ web_server: logger: level: DEBUG - -# http_request: -# verify_ssl: false wifi: networks: @@ -28,9 +25,6 @@ wifi: - ssid: SSID password: WPA_KEY -# ota: -# - platform: http_request - # i2c: # sda: D2 # scl: D1 diff --git a/images/nodered_1.png b/images/nodered_1.png index 64d14cc5..2fb12e16 100644 Binary files a/images/nodered_1.png and b/images/nodered_1.png differ diff --git a/images/nodered_2.png b/images/nodered_2.png index 55443fe0..ad8fb0e4 100644 Binary files a/images/nodered_2.png and b/images/nodered_2.png differ diff --git a/input_text.yaml b/input_text.yaml index d4d2f097..fed8e971 100644 --- a/input_text.yaml +++ b/input_text.yaml @@ -2,6 +2,9 @@ # electricity_cost_monthly: # name: "Electricity Cost" +electricity_cost_monthly_tesla: + name: "Tesla Electricity Cost" + electricity_cost_monthly_emporia: name: "Electricity Cost" diff --git a/packages/tesla.yaml b/packages/tesla.yaml new file mode 100644 index 00000000..e8e1b8cc --- /dev/null +++ b/packages/tesla.yaml @@ -0,0 +1,695 @@ +mqtt: + - sensor: + name: Tesla Display Name + object_id: tesla_display_name # entity_id + unique_id: teslamate_1_display_name # internal id, used for device grouping + availability: &teslamate_availability + - topic: teslamate/cars/1/healthy + payload_available: 'true' + payload_not_available: 'false' + device: &teslamate_device_info + identifiers: [teslamate_car_1] + configuration_url: https://teslamate.zxxz.io/ + manufacturer: Tesla + model: Model S + name: Tesla Model S + state_topic: "teslamate/cars/1/display_name" + icon: mdi:car + + - device_tracker: + name: Tesla Location + object_id: tesla_location + unique_id: teslamate_1_location + availability: *teslamate_availability + device: *teslamate_device_info + json_attributes_topic: "teslamate/cars/1/location" + icon: mdi:crosshairs-gps + + - device_tracker: + name: Tesla Active route location + object_id: tesla_active_route_location + unique_id: teslamate_1_active_route_location + availability: &teslamate_active_route_availability + - topic: "teslamate/cars/1/active_route" + value_template: "{{ 'offline' if value_json.error else 'online' }}" + device: *teslamate_device_info + json_attributes_topic: "teslamate/cars/1/active_route" + json_attributes_template: "{{ value_json.location | tojson }}" + icon: mdi:crosshairs-gps + + - sensor: + name: Tesla State + object_id: tesla_state + unique_id: teslamate_1_state + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/state" + icon: mdi:car-connected + + - sensor: + name: Tesla Since + object_id: tesla_since + unique_id: teslamate_1_since + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/since" + device_class: timestamp + icon: mdi:clock-outline + + - sensor: + name: Tesla Version + object_id: tesla_version + unique_id: teslamate_1_version + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/version" + icon: mdi:alphabetical + + - sensor: + name: Tesla Update Version + object_id: tesla_update_version + unique_id: teslamate_1_update_version + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/update_version" + icon: mdi:alphabetical + + - sensor: + name: Tesla Geofence + object_id: tesla_geofence + unique_id: teslamate_1_geofence + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/geofence" + icon: mdi:earth + + - sensor: + name: Tesla Shift State + object_id: tesla_shift_state + unique_id: teslamate_1_shift_state + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/shift_state" + icon: mdi:car-shift-pattern + + - sensor: + name: Tesla Power + object_id: tesla_power + unique_id: teslamate_1_power + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/power" + device_class: power + unit_of_measurement: kW + icon: mdi:flash + + - sensor: + name: Tesla Speed + object_id: tesla_speed + unique_id: teslamate_1_speed + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/speed" + unit_of_measurement: "mi/h" + icon: mdi:speedometer + value_template: "{{ ((value | float) / 1.609344) | round(2) }}" + +# - sensor: +# name: Tesla Heading +# object_id: tesla_heading +# unique_id: teslamate_1_heading +# availability: *teslamate_availability +# device: *teslamate_device_info +# state_topic: "teslamate/cars/1/heading" +# unit_of_measurement: ° +# icon: mdi:compass + + - sensor: + name: Tesla Elevation + object_id: tesla_elevation + unique_id: teslamate_1_elevation + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/elevation" + unit_of_measurement: ft + icon: mdi:image-filter-hdr + value_template: "{{ ((value | float) * 3.2808 ) | round(2) }}" + + - sensor: + name: Tesla Inside Temp + object_id: tesla_inside_temp + unique_id: teslamate_1_inside_temp + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/inside_temp" + device_class: temperature + unit_of_measurement: °C + icon: mdi:thermometer-lines + + - sensor: + name: Tesla Outside Temp + object_id: tesla_outside_temp + unique_id: teslamate_1_outside_temp + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/outside_temp" + device_class: temperature + unit_of_measurement: °C + icon: mdi:thermometer-lines + + - sensor: + name: Tesla Odometer + object_id: tesla_odometer + unique_id: teslamate_1_odometer + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/odometer" + unit_of_measurement: mi + icon: mdi:counter + value_template: "{{ ((value | float) / 1.609344) | round(2) }}" + + - sensor: + name: Tesla Est Battery Range + object_id: tesla_est_battery_range + unique_id: teslamate_1_est_battery_range + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/est_battery_range_km" + unit_of_measurement: mi + icon: mdi:gauge + value_template: "{{ ((value | float) / 1.609344) | round(2) }}" + + - sensor: + name: Tesla Rated Battery Range + object_id: tesla_rated_battery_range + unique_id: teslamate_1_rated_battery_range + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/rated_battery_range_km" + unit_of_measurement: mi + icon: mdi:gauge + value_template: "{{ ((value | float) / 1.609344) | round(2) }}" + + - sensor: + name: Tesla Ideal Battery Range + object_id: tesla_ideal_battery_range + unique_id: teslamate_1_ideal_battery_range + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/ideal_battery_range_km" + unit_of_measurement: mi + icon: mdi:gauge + value_template: "{{ ((value | float) / 1.609344) | round(2) }}" + + - sensor: + name: Tesla Battery Level + object_id: tesla_battery_level + unique_id: teslamate_1_battery_level + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/battery_level" + device_class: battery + unit_of_measurement: "%" + icon: mdi:battery-80 + + - sensor: + name: Tesla Usable Battery Level + object_id: tesla_usable_battery_level + unique_id: teslamate_1_usable_battery_level + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/usable_battery_level" + unit_of_measurement: "%" + icon: mdi:battery-80 + + - sensor: + name: Tesla Charge Energy Added + object_id: tesla_charge_energy_added + unique_id: teslamate_1_charge_energy_added + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/charge_energy_added" + device_class: energy + unit_of_measurement: kWh + icon: mdi:battery-charging + + - sensor: + name: Tesla Charge Limit Soc + object_id: tesla_charge_limit_soc + unique_id: teslamate_1_charge_limit_soc + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/charge_limit_soc" + unit_of_measurement: "%" + icon: mdi:battery-charging-100 + + - sensor: + name: Tesla Charger Actual Current + object_id: tesla_charger_actual_current + unique_id: teslamate_1_charger_actual_current + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/charger_actual_current" + device_class: current + unit_of_measurement: A + icon: mdi:lightning-bolt + + - sensor: + name: Tesla Charger Phases + object_id: tesla_charger_phases + unique_id: teslamate_1_charger_phases + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/charger_phases" + icon: mdi:sine-wave + + - sensor: + name: Tesla Charger Power + object_id: tesla_charger_power + unique_id: teslamate_1_charger_power + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/charger_power" + device_class: power + unit_of_measurement: kW + icon: mdi:lightning-bolt + + - sensor: + name: Tesla Charger Voltage + object_id: tesla_charger_voltage + unique_id: teslamate_1_charger_voltage + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/charger_voltage" + device_class: voltage + unit_of_measurement: V + icon: mdi:lightning-bolt + +# - sensor: +# name: Tesla Scheduled Charging Start Time +# object_id: tesla_scheduled_charging_start_time +# unique_id: teslamate_1_scheduled_charging_start_time +# availability: *teslamate_availability +# device: *teslamate_device_info +# state_topic: "teslamate/cars/1/scheduled_charging_start_time" +# device_class: timestamp +# icon: mdi:clock-outline + + - sensor: + name: Tesla Time To Full Charge + object_id: tesla_time_to_full_charge + unique_id: teslamate_1_time_to_full_charge + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/time_to_full_charge" + unit_of_measurement: h + icon: mdi:clock-outline + + - sensor: + name: Tesla TPMS Pressure Front Left + object_id: tesla_tpms_pressure_fl + unique_id: teslamate_1_tpms_pressure_fl + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/tpms_pressure_fl" + unit_of_measurement: psi + icon: mdi:car-tire-alert + value_template: "{{ ((value | float) * 14.50377) | round(2) }}" + + - sensor: + name: Tesla TPMS Pressure Front Right + object_id: tesla_tpms_pressure_fr + unique_id: teslamate_1_tpms_pressure_fr + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/tpms_pressure_fr" + unit_of_measurement: psi + icon: mdi:car-tire-alert + value_template: "{{ ((value | float) * 14.50377) | round(2) }}" + + - sensor: + name: Tesla TPMS Pressure Rear Left + object_id: tesla_tpms_pressure_rl + unique_id: teslamate_1_tpms_pressure_rl + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/tpms_pressure_rl" + unit_of_measurement: psi + icon: mdi:car-tire-alert + value_template: "{{ ((value | float) * 14.50377) | round(2) }}" + + - sensor: + name: Tesla TPMS Pressure Rear Right + object_id: tesla_tpms_pressure_rr + unique_id: teslamate_1_tpms_pressure_rr + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/tpms_pressure_rr" + unit_of_measurement: psi + icon: mdi:car-tire-alert + value_template: "{{ ((value | float) * 14.50377) | round(2) }}" + + - sensor: + name: Tesla Active route destination + object_id: tesla_active_route_destination + unique_id: teslamate_1_active_route_destination + availability: *teslamate_active_route_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/active_route" + value_template: "{{ value_json.destination }}" + icon: mdi:map-marker + + - sensor: + name: Tesla Active route energy at arrival + object_id: tesla_active_route_energy_at_arrival + unique_id: teslamate_1_active_route_energy_at_arrival + availability: *teslamate_active_route_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/active_route" + value_template: "{{ value_json.energy_at_arrival }}" + unit_of_measurement: "%" + icon: mdi:battery-80 + + - sensor: + name: Tesla Active route distance to arrival (mi) + object_id: tesla_active_route_distance_to_arrival_mi + unique_id: teslamate_1_active_route_distance_to_arrival_mi + availability: *teslamate_active_route_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/active_route" + value_template: "{{ value_json.miles_to_arrival }}" + unit_of_measurement: mi + icon: mdi:map-marker-distance + + - sensor: + name: Tesla Active route minutes to arrival + object_id: tesla_active_route_minutes_to_arrival + unique_id: teslamate_1_active_route_minutes_to_arrival + availability: *teslamate_active_route_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/active_route" + value_template: "{{ value_json.minutes_to_arrival }}" + unit_of_measurement: min + icon: mdi:clock-outline + + - sensor: + name: Tesla Active route traffic minutes delay + object_id: tesla_active_route_traffic_minutes_delay + unique_id: teslamate_1_active_route_traffic_minutes_delay + availability: *teslamate_active_route_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/active_route" + value_template: "{{ value_json.traffic_minutes_delay }}" + unit_of_measurement: min + icon: mdi:clock-alert-outline + + - binary_sensor: + name: Tesla Healthy + object_id: tesla_healthy + unique_id: teslamate_1_healthy + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/healthy" + payload_on: "true" + payload_off: "false" + icon: mdi:heart-pulse + + - binary_sensor: + name: Tesla Update Available + object_id: tesla_update_available + unique_id: teslamate_1_update_available + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/update_available" + payload_on: "true" + payload_off: "false" + icon: mdi:alarm + + - binary_sensor: + name: Tesla Locked + object_id: tesla_locked + unique_id: teslamate_1_locked + availability: *teslamate_availability + device: *teslamate_device_info + device_class: lock + state_topic: "teslamate/cars/1/locked" + payload_on: "false" + payload_off: "true" + + - binary_sensor: + name: Tesla Sentry Mode + object_id: tesla_sentry_mode + unique_id: teslamate_1_sentry_mode + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/sentry_mode" + payload_on: "true" + payload_off: "false" + icon: mdi:cctv + + - binary_sensor: + name: Tesla Windows Open + object_id: tesla_windows_open + unique_id: teslamate_1_windows_open + availability: *teslamate_availability + device: *teslamate_device_info + device_class: window + state_topic: "teslamate/cars/1/windows_open" + payload_on: "true" + payload_off: "false" + icon: mdi:car-door + + - binary_sensor: + name: Tesla Doors Open + object_id: tesla_doors_open + unique_id: teslamate_1_doors_open + availability: *teslamate_availability + device: *teslamate_device_info + device_class: door + state_topic: "teslamate/cars/1/doors_open" + payload_on: "true" + payload_off: "false" + icon: mdi:car-door + + - binary_sensor: + name: Tesla Trunk Open + object_id: tesla_trunk_open + unique_id: teslamate_1_trunk_open + availability: *teslamate_availability + device: *teslamate_device_info + device_class: opening + state_topic: "teslamate/cars/1/trunk_open" + payload_on: "true" + payload_off: "false" + icon: mdi:car-side + + - binary_sensor: + name: Tesla Frunk Open + object_id: tesla_frunk_open + unique_id: teslamate_1_frunk_open + availability: *teslamate_availability + device: *teslamate_device_info + device_class: opening + state_topic: "teslamate/cars/1/frunk_open" + payload_on: "true" + payload_off: "false" + icon: mdi:car-side + + - binary_sensor: + name: Tesla Is User Present + object_id: tesla_is_user_present + unique_id: teslamate_1_is_user_present + availability: *teslamate_availability + device: *teslamate_device_info + device_class: presence + state_topic: "teslamate/cars/1/is_user_present" + payload_on: "true" + payload_off: "false" + icon: mdi:human-greeting + + - binary_sensor: + name: Tesla Is Climate On + object_id: tesla_is_climate_on + unique_id: teslamate_1_is_climate_on + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/is_climate_on" + payload_on: "true" + payload_off: "false" + icon: mdi:fan + + - binary_sensor: + name: Tesla Is Preconditioning + object_id: tesla_is_preconditioning + unique_id: teslamate_1_is_preconditioning + availability: *teslamate_availability + device: *teslamate_device_info + state_topic: "teslamate/cars/1/is_preconditioning" + payload_on: "true" + payload_off: "false" + icon: mdi:fan + + - binary_sensor: + name: Tesla Plugged In + object_id: tesla_plugged_in + unique_id: teslamate_1_plugged_in + availability: *teslamate_availability + device: *teslamate_device_info + device_class: plug + state_topic: "teslamate/cars/1/plugged_in" + payload_on: "true" + payload_off: "false" + icon: mdi:ev-station + + - binary_sensor: + name: Tesla Charge Port Door OPEN + object_id: tesla_charge_port_door_open + unique_id: teslamate_1_charge_port_door_open + availability: *teslamate_availability + device: *teslamate_device_info + device_class: opening + state_topic: "teslamate/cars/1/charge_port_door_open" + payload_on: "true" + payload_off: "false" + icon: mdi:ev-plug-tesla + +timer: + tesla_charge_backoff: + name: Tesla Charge Backoff + duration: "00:30:00" + restore: true + +automation: + - alias: "Tesla Auto Open Garage" + id: "tesla_auto_open_garage" + initial_state: on + mode: single + trigger: + platform: state + entity_id: device_tracker.tesla_location + from: "not_home" + to: "home" + condition: "{{ is_state('binary_sensor.tesla_is_user_present', 'on') }}" + action: + - if: "{{ is_state('cover.garage_door', 'closed') }}" + alias: Open Garage + then: + - service: input_boolean.turn_off + entity_id: input_boolean.security_status + - service: cover.open_cover + entity_id: cover.garage_door + - service: script.notify_wrapper + data: + message: "Tesla Auto Opened Garage" + - delay: "00:05:00" + - if: "{{ is_state('switch.garage_lights', 'off') }}" + alias: Turn On Garage Lights + then: + - service: switch.turn_on + entity_id: switch.garage_lights + + - alias: "Auto Lower Charge Rate" + id: "auto_lower_charge_rate" + initial_state: on + trigger: + - platform: numeric_state + id: total + entity_id: sensor.total_power + above: 15000 + - platform: numeric_state + id: dryer + entity_id: sensor.dryer_power + above: 5000 + - platform: numeric_state + id: oven + entity_id: sensor.oven_power + above: 5000 + action: + - if: "{{ (states('sensor.total_power') | int) < 15000}}" + alias: "Less than 15k" + then: + - action: emporia_vue.set_charger_current + data: + current: 20 + target: + entity_id: switch.emporia_charger + - action: timer.start + data: + duration: "00:15:00" + target: + entity_id: timer.tesla_charge_backoff + - if: "{{ state_attr('switch.emporia_charger','charging_rate') != 20 }}" + then: + - action: script.notify_wrapper + data: + message: Charge rate automation triggered by {{ trigger.id }}! Total power {{ states('sensor.total_power') }}W. Limiting charge rate to 20A. + data: + priority: "{% if (is_state('sensor.tesla_state', 'charging') and state_attr('switch.emporia_charger','charging_rate') < 20) %}1{% else %}0{% endif %}" + else: + - action: emporia_vue.set_charger_current + data: + current: 1 + target: + entity_id: switch.emporia_charger + # - action: switch.turn_off + # entity_id: switch.emporia_charger + - action: timer.start + data: + duration: "00:15:00" + target: + entity_id: timer.tesla_charge_backoff + - if: "{{ state_attr('switch.emporia_charger','charging_rate') != 1 }}" + then: + - action: script.notify_wrapper + data: + message: Total power has exceeded 15kW! Total power {{ states('sensor.total_power') }}W. Limiting charge rate to 1A. + data: + priority: 1 + + - alias: "Auto Raise Charge Rate" + id: auto_raise_charge_rate + initial_state: on + trigger: + - platform: event + id: finish + event_type: + - timer.finished + - timer.cancelled + event_data: + entity_id: timer.tesla_charge_backoff + action: + - action: switch.turn_on + entity_id: switch.emporia_charger + - action: script.notify_wrapper + data: + message: Timer expired, increasing charge rate to 40A. + - action: emporia_vue.set_charger_current + data: + current: 40 + target: + entity_id: switch.emporia_charger + + - id: update_tesla_charging_cost + alias: Update Tesla Charging Cost + trigger: + - platform: time_pattern + minutes: /5 + condition: "{{ is_state('sensor.tesla_state', 'charging') and is_state('device_tracker.tesla_location', 'home') }}" + action: + - alias: Tesla Electricity + action: python_script.compute_utility_costs + data: + meter_entity: sensor.tesla_energy_this_month + + - alias: "AC Adjustment Near Arrival" + id: tesla_ac_adjustment_for_arrival + trigger: + platform: numeric_state + entity_id: sensor.tesla_active_route_minutes_to_arrival + below: 31 + condition: "{{ is_state('sensor.tesla_active_route_destination','home')}}" + action: + - action: script.notify_wrapper + data: + message: Adjusting AC prior to arrival based on Tesla location. + - action: rest_command.adjust_morning \ No newline at end of file diff --git a/python_scripts/compute_utility_costs.py b/python_scripts/compute_utility_costs.py index 761b13f5..ca294e48 100644 --- a/python_scripts/compute_utility_costs.py +++ b/python_scripts/compute_utility_costs.py @@ -1,16 +1,15 @@ MeterEntity = data.get('meter_entity') inputState = hass.states.get(MeterEntity).state -if MeterEntity == "sensor.electricity_usage": - ''' - Electric: - 1. Service charge: $7.00 per month; plus - 2. Energy charge: $0.1187 per kWh for all kWh; plus - 3. Transmission Delivery Adjustment: $0.0175 per kWh. - ''' - - current_cost = 0.1187 + 0.0175 +''' +Electric: +1. Service charge: $7.00 per month; plus +2. Energy charge: $0.1187 per kWh for all kWh; plus +3. Transmission Delivery Adjustment: $0.0175 per kWh. +''' +current_cost = 0.1187 + 0.0175 +if MeterEntity == "sensor.electricity_usage": #hass.bus.fire("debug", {"wow": ""}) # Add $7 monthly charge to summary total @@ -20,6 +19,13 @@ service_data = {"entity_id": "input_text.electricity_cost_monthly_emporia", "value": computed_electricity_cost} hass.services.call("input_text", "set_value", service_data) +elif MeterEntity == "sensor.tesla_energy_this_month": + # Add $7 monthly charge to summary total + computed_electricity_cost = round((float(inputState) * current_cost), 2) + + # Set State + service_data = {"entity_id": "input_text.electricity_cost_monthly_tesla", "value": computed_electricity_cost} + hass.services.call("input_text", "set_value", service_data) elif MeterEntity == "sensor.water_usage": unaccountedusage = int(float(inputState)) diff --git a/ui-lovelace/.cards/thermostat.yaml b/ui-lovelace/.cards/thermostat.yaml index 184fd1a9..dd8fde07 100644 --- a/ui-lovelace/.cards/thermostat.yaml +++ b/ui-lovelace/.cards/thermostat.yaml @@ -34,8 +34,8 @@ sensors: name: Water Supply Closet - entity: sensor.netatmo_home_attic_temperature name: Attic - - entity: sensor.tesla_temperature_outside - - entity: sensor.tesla_temperature_inside + - entity: sensor.tesla_inside_temp + name: Tesla Interior - entity: sensor.ac_runtime_today name: Today - entity: sensor.ac_runtime_yesterday diff --git a/ui-lovelace/05-server.yaml b/ui-lovelace/05-server.yaml index 45eb0c89..a893787e 100644 --- a/ui-lovelace/05-server.yaml +++ b/ui-lovelace/05-server.yaml @@ -109,6 +109,8 @@ cards: - type: markdown content: > + Monthly Tesla Home Charging Cost: ${{ states('input_text.electricity_cost_monthly_tesla') }} + Monthly Electric Cost Emporia: ${{ states('input_text.electricity_cost_monthly_emporia') }} Monthly Water Cost: ${{ states('input_text.water_cost_monthly') }} diff --git a/ui-lovelace/06-car.yaml b/ui-lovelace/06-car.yaml new file mode 100644 index 00000000..254cc657 --- /dev/null +++ b/ui-lovelace/06-car.yaml @@ -0,0 +1,149 @@ +path: car +title: Car +badges: [] +icon: mdi:car-connected +cards: + - type: vertical-stack + cards: + - type: glance + entities: + - entity: sensor.tesla_battery_level + name: Battery Level + - entity: sensor.tesla_state + name: Car State + - entity: binary_sensor.tesla_plugged_in + name: Plugged In + - type: glance + entities: + - entity: sensor.tesla_shift_state + name: Park Brake + - entity: binary_sensor.tesla_sentry_mode + name: Sentry Mode + - entity: sensor.tesla_speed + name: Speed + - type: glance + entities: + - entity: binary_sensor.tesla_healthy + name: Car Health + - entity: binary_sensor.tesla_windows_open + name: Window Status + - type: button + entity: binary_sensor.tesla_locked + name: Doors + show_state: true + state: + - value: locked + icon: mdi:lock + color: green + - value: unlocked + icon: mdi:lock-open + color: red + + - type: vertical-stack + cards: + - type: gauge + entity: sensor.total_power + graph: line + min: 300 + max: 22000 + - type: entities + entities: + - switch.emporia_charger + - sensor.tesla_miles_per_month + - sensor.tesla_energy_this_month + - entity: sensor.tesla_charger_actual_current + name: Charger Current + - entity: sensor.tesla_charger_power + name: Charger Power + - entity: sensor.tesla_charger_voltage + name: Charger Voltage + - entity: sensor.tesla_time_to_full_charge + name: Time To Full Charge + - type: markdown + content: > + + Tesla Home Charging Cost This Month: ${{ states('input_text.electricity_cost_monthly_tesla') }} + + - type: entities + entities: + - entity: sensor.tesla_state + name: Status + - entity: sensor.tesla_since + name: Last Status Change + - entity: binary_sensor.tesla_healthy + name: Logger Healthy + - entity: sensor.tesla_version + name: Software Version + - entity: binary_sensor.tesla_update_available + name: Available Update Status + - entity: sensor.tesla_update_version + name: Available Update Version + - entity: sensor.tesla_geofence + name: Geo-fence Name + - device_tracker.tesla_location + - entity: sensor.tesla_shift_state + name: Shifter State + - entity: sensor.tesla_speed + name: Speed + - entity: sensor.tesla_elevation + name: Elevation + - entity: binary_sensor.tesla_locked + name: Locked + - entity: binary_sensor.tesla_sentry_mode + name: Sentry Mode Enabled + - entity: binary_sensor.tesla_windows_open + name: Windows Open + - entity: binary_sensor.tesla_doors_open + name: Doors Open + - entity: binary_sensor.tesla_trunk_open + name: Trunk Open + - entity: binary_sensor.tesla_frunk_open + name: Frunk Open + - entity: binary_sensor.tesla_is_user_present + name: User Present + - entity: binary_sensor.tesla_is_climate_on + name: Climate On + - entity: sensor.tesla_inside_temp + name: Inside Temperature + - entity: sensor.tesla_outside_temp + name: Outside Temperature + - entity: binary_sensor.tesla_is_preconditioning + name: Preconditioning + - entity: sensor.tesla_odometer + name: Odometer + - entity: sensor.tesla_est_battery_range + name: Estimated Battery Range + - entity: sensor.tesla_rated_battery_range + name: Rated Battery Range + - entity: sensor.tesla_ideal_battery_range + name: Ideal Battery Range + - entity: sensor.tesla_battery_level + name: Battery Level + - entity: sensor.tesla_usable_battery_level + name: Usable Battery Level + - entity: binary_sensor.tesla_plugged_in + name: Plugged In + - entity: sensor.tesla_charge_energy_added + name: Charge Energy Added + - entity: sensor.tesla_charge_limit_soc + name: Charge Limit + - entity: binary_sensor.tesla_charge_port_door_open + name: Charge Port Door Open + - entity: sensor.tesla_tpms_pressure_fl + name: Front Left Tire Pressure + - entity: sensor.tesla_tpms_pressure_fr + name: Front Right Tire Pressure + - entity: sensor.tesla_tpms_pressure_rl + name: Rear Left Tire Pressure + - entity: sensor.tesla_tpms_pressure_rr + name: Rear Right Tire Pressure + - entity: sensor.tesla_active_route_destination + name: Active Route Destination + - entity: sensor.tesla_active_route_energy_at_arrival + name: Active Route Energy at Arrival + - entity: sensor.tesla_active_route_distance_to_arrival_mi + name: Active Route Distance to Arrival (mi) + - entity: sensor.tesla_active_route_minutes_to_arrival + name: Active Route Minutes to Arrival + - entity: sensor.tesla_active_route_traffic_minutes_delay + name: Active Route Traffic Minutes Delay diff --git a/ui-lovelace/15-tesla.yaml b/ui-lovelace/15-tesla.yaml new file mode 100644 index 00000000..d7612e4f --- /dev/null +++ b/ui-lovelace/15-tesla.yaml @@ -0,0 +1,153 @@ +title: Tablet +visible: false +type: panel +path: tesla +cards: + - type: horizontal-stack + cards: + # Column 1 + - type: vertical-stack + cards: + - type: custom:mushroom-climate-card + entity: climate.thermostat + show_temperature_control: true + + - type: custom:mushroom-entity-card + entity: input_boolean.security_status + tap_action: + action: toggle + + - type: custom:mushroom-entity-card + entity: cover.garage_door + tap_action: + action: toggle + card_mod: + style: | + @keyframes blink { + 50% { + {% if states('cover.garage_door') == "open" %} + background: red; + {% endif %} + } + } + ha-card { + {% if states('cover.garage_door') == "open" %} + animation: blink 1s linear infinite; + {% endif %} + } + + - type: custom:mushroom-entity-card + entity: lock.front_door + tap_action: + action: toggle + card_mod: + style: | + @keyframes blink { + 50% { + {% if states('lock.front_door') == "unlocked" %} + background: red; + {% endif %} + } + } + ha-card { + {% if states('lock.front_door') == "unlocked" %} + animation: blink 1s linear infinite; + {% endif %} + } + + - type: custom:mushroom-entity-card + entity: lock.back_door + tap_action: + action: toggle + card_mod: + style: | + @keyframes blink { + 50% { + {% if states('lock.front_door') == "unlocked" %} + background: red; + {% endif %} + } + } + ha-card { + {% if states('lock.front_door') == "unlocked" %} + animation: blink 1s linear infinite; + {% endif %} + } + + - type: custom:mushroom-entity-card + entity: lock.garage_exterior_door + tap_action: + action: toggle + card_mod: + style: | + @keyframes blink { + 50% { + {% if states('lock.front_door') == "unlocked" %} + background: red; + {% endif %} + } + } + ha-card { + {% if states('lock.front_door') == "unlocked" %} + animation: blink 1s linear infinite; + {% endif %} + } + + - type: vertical-stack + cards: + - type: picture-entity + entity: camera.driveway + + - type: picture-entity + entity: camera.back_porch + + # Column 2 + - type: vertical-stack + cards: + #- !include .cards/kitchen_timer.yaml + + - type: custom:mushroom-entity-card + entity: switch.garage_lights + icon: mdi:lightbulb + tap_action: + action: toggle + + - type: custom:mushroom-entity-card + entity: group.kitchen + icon: mdi:countertop + tap_action: + action: toggle + + - type: custom:mushroom-entity-card + entity: group.living_room + icon: mdi:sofa-outline + tap_action: + action: toggle + + - type: custom:mushroom-entity-card + entity: group.master_bedroom + icon: mdi:bed + tap_action: + action: toggle + + # - type: custom:mushroom-entity-card + # entity: group.christmas + # icon: mdi:forest + # tap_action: + # action: toggle + + - type: sensor + entity: sensor.total_power + graph: line + detail: 2 + hours_to_show: 8 + + - !include .cards/water_flow.yaml + + - type: vertical-stack + cards: + - type: picture-entity + entity: camera.front_door + + - type: picture-entity + entity: camera.garage \ No newline at end of file diff --git a/www/community/lovelace-wallpanel/wallpanel.js b/www/community/lovelace-wallpanel/wallpanel.js index 8afaa1c1..81605448 100644 --- a/www/community/lovelace-wallpanel/wallpanel.js +++ b/www/community/lovelace-wallpanel/wallpanel.js @@ -107,7 +107,7 @@ class ScreenWakeLock { } } -const version = "4.29.0"; +const version = "4.29.1"; const defaultConfig = { enabled: false, enabled_on_tabs: [], @@ -359,6 +359,9 @@ function mergeConfig(target, ...sources) { if (typeof val === 'string' || val instanceof String) { val = val.replace(/\$\{entity:\s*([^}]+\.[^}]+)\}/g, replacer); } + if (typeof target[key] === 'boolean') { + val = ["true", "on", "yes", "1"].includes(val.toString()); + } Object.assign(target, { [key]: val }); } } @@ -408,7 +411,7 @@ function updateConfig() { config = mergeConfig(config, config.profiles[profile]); logger.debug(`Profile set from entity state: ${profile}`); } - + if (config.card_interaction) { config.stop_screensaver_on_mouse_move = false; } diff --git a/www/community/lovelace-wallpanel/wallpanel.js.gz b/www/community/lovelace-wallpanel/wallpanel.js.gz index b4a0206f..e312e904 100644 Binary files a/www/community/lovelace-wallpanel/wallpanel.js.gz and b/www/community/lovelace-wallpanel/wallpanel.js.gz differ