diff --git a/addons/repositories.yaml b/addons/repositories.yaml index 0420c6c..40c343b 100644 --- a/addons/repositories.yaml +++ b/addons/repositories.yaml @@ -1,7 +1,3 @@ -Add-On Repository for Cloudflare: - maintainer: Tobia Brenner - slug: 9074a9fa - source: https://github.com/brenner-tobias/ha-addons Alex's Add-ons Shack: maintainer: Alex van den Hoogen slug: 2ca71ec5 @@ -10,6 +6,10 @@ B Tasker HomeAssistant Addons: maintainer: B Tasker slug: 93f0ddc5 source: https://github.com/bentasker/HomeAssistantAddons +Cloudflared: + maintainer: Tobia Brenner + slug: 9074a9fa + source: https://github.com/brenner-tobias/ha-addons EMHASS Add-on Energy Management for Home Assistant: maintainer: David HERNANDEZ slug: 5b918bf2 @@ -42,6 +42,10 @@ Home Assistant Google Drive Backup Repository: maintainer: Stephen Beechen slug: cebe7a76 source: https://github.com/sabeechen/hassio-google-drive-backup +MatterVN Hass.io Add-ons: + maintainer: TTVTien + slug: 4ee6ccd4 + source: https://github.com/TenySmart/HassioAddon MickMake Hass.io Add-ons: maintainer: MickMake slug: ba22da74 @@ -54,10 +58,6 @@ Shortumations: maintainer: Ari Sosnovsky slug: 04377e81 source: https://github.com/asosnovsky/Shortumation -TenySmart Hass.io Add-ons: - maintainer: TTVTien - slug: 4ee6ccd4 - source: https://github.com/TenySmart/HassioAddon bjeanes Home Assistant add-on repository: maintainer: Bo Jeanes slug: 9c51689a diff --git a/config/.HA_VERSION b/config/.HA_VERSION index 8898b90..c39a707 100644 --- a/config/.HA_VERSION +++ b/config/.HA_VERSION @@ -1 +1 @@ -2022.8.5 \ No newline at end of file +2023.4.6 \ No newline at end of file diff --git a/config/automations.yaml b/config/automations.yaml index a99222d..cc20494 100644 --- a/config/automations.yaml +++ b/config/automations.yaml @@ -68,3 +68,44 @@ before: sunset action: service: openuv.update_data +- id: '1661989262917' + alias: Control Living Room Lights + description: '' + trigger: + - id: brightness + platform: state + entity_id: + - sensor.living_room_light_dimmer_action + to: + - brightness_move_down + - brightness_move_up + - brightness_stop + - id: toggle + platform: state + to: toggle + entity_id: + - sensor.living_room_light_dimmer_action + condition: [] + action: + - choose: + - conditions: + - condition: template + value_template: '{{ trigger.id == ''toggle'' }}' + sequence: + - service: light.toggle + target: + area_id: living_room + data: + transition: 1 + - conditions: + - condition: template + value_template: '{{ trigger.id == ''brightness'' }}' + sequence: + - service: light.turn_on + data: + transition: 0.1 + brightness: '{{ state_attr(''sensor.living_room_light_dimmer_action'', ''brightness'') + | int }}' + target: + area_id: living_room + mode: queued diff --git a/config/configuration.yaml b/config/configuration.yaml index b0f0f71..973d302 100644 --- a/config/configuration.yaml +++ b/config/configuration.yaml @@ -17,7 +17,7 @@ homeassistant: recorder: db_url: !secret recorder_db commit_interval: 30 - purge_keep_days: 60 + purge_keep_days: 14 http: use_x_forwarded_for: true diff --git a/config/customize.yaml b/config/customize.yaml index 7088ff9..0967ef4 100644 --- a/config/customize.yaml +++ b/config/customize.yaml @@ -1,8 +1 @@ -sensor.rtorrent_all_torrents: - unit_of_measurement: torrents -sensor.rtorrent_active_torrents: - unit_of_measurement: torrents -sensor.rtorrent_downloading_torrents: - unit_of_measurement: torrents -sensor.rtorrent_uploading_torrents: - unit_of_measurement: torrents +{} diff --git a/config/music_assistant.db.old b/config/music_assistant.db.old new file mode 100644 index 0000000..5e4d008 Binary files /dev/null and b/config/music_assistant.db.old differ diff --git a/config/packages/climate.yaml b/config/packages/climate.yaml new file mode 100644 index 0000000..f1df16a --- /dev/null +++ b/config/packages/climate.yaml @@ -0,0 +1,26 @@ +# TODO: +# +# * Turn on AC when: someone is home, weather outside is cold, and are out of bed or about to get out of bed +# - maybe can change the logic that manages the blinds using the sleep/wake logic to be backed by a schedule state that multiple things can key off? +automation: + - alias: "Living Room AC Ionizer" + trigger: + platform: state + entity_id: climate.living_room_a_c + not_to: + - unavailable + - unknown + not_from: + - unavailable + - unknown + condition: + condition: template + value_template: '{{ trigger.to_state.state != "off" }}' + action: + - service: switch.turn_on + entity_id: switch.living_room_a_c_ionizer + - service: climate.set_fan_mode + data: + fan_mode: NATURE + target: + entity_id: climate.living_room_a_c diff --git a/config/packages/dummy.yaml b/config/packages/dummy.yaml index 480caee..5c38b90 100644 --- a/config/packages/dummy.yaml +++ b/config/packages/dummy.yaml @@ -6,6 +6,8 @@ sensor: - platform: statistics # Force statistics integration to be loaded (even if no other sensors) so I can reload without restarting HA name: "dummy_statistics" unique_id: dummy + sampling_size: 20 + state_characteristic: mean entity_id: sensor.energy_production_tomorrow - platform: filter # Force filter integration to be loaded (even if no other sensors) so I can reload without restarting HA diff --git a/config/packages/energy.yaml b/config/packages/energy.yaml index 03c1012..c109310 100644 --- a/config/packages/energy.yaml +++ b/config/packages/energy.yaml @@ -31,6 +31,23 @@ utility_meter: name: Energy exported cycle: daily + # daily_supply_charge: + # unique_id: 31887b27e2ecd837328b + +template: + - trigger: + - platform: time_pattern + hours: "*" # calculate hourly should be fine + sensor: + # Increases every day by 1W to fake a daily supply charge in energy dashboard. + - state: >- + {{ 0.001 * (now() - "2022-09-26" | as_datetime | as_local).days }} + unit_of_measurement: kWh + state_class: total_increasing + device_class: energy + unique_id: 3970c65019ebd336b074 + name: "Days for daily supply charge" + automation: - id: b508954f792ff8483254 alias: Change electricity tariff @@ -73,39 +90,23 @@ rest_command: User-Agent: HomeAssistant X-Pvoutput-Apikey: !secret pvoutput_api_key X-Pvoutput-SystemId: !secret pvoutput_system_id - payload: >- - d={{now().strftime("%Y%m%d")}} {#- date -#} - &t={{now().strftime("%H:%M")}} {#- time -#} - &c1=2 {#- cumulative mode -#} - &v1={{(states('sensor.inverter_pv_generation_today')|float * 1000)|round(0) }} - {#- energy generation (Wh) -#} - &v2={{states('sensor.inverter_active_power')|float|round(0)}} {#- power generation (W) -#} - &v3= {#- energy consumption (Wh) -#} - &v4={{states('sensor.household_power_demand')|float|round(0)}} {#- power consumption (W) -#} - {#- &v5={{states('sensor.home_weather_temperature')|float|round(1)}} {#- panel temperature? -#} - &v6={{states('sensor.inverter_phase_a_voltage')|float|round(1)}} {#- voltage -#} + payload: "{{ states('sensor.pvoutput_payload') }}" content_type: "application/x-www-form-urlencoded" sensor: - platform: template sensors: - # energy_import_price: - # unique_id: 2b80f57455c84e873952 - # friendly_name: Energy import price - # value_template: >- - # {%- if is_state('select.daily_energy_import', 'peak') -%} - # 0.23320 - # {%- else -%} - # 0.15235 - # {%- endif -%} - # unit_of_measurement: AUD - # device_class: monetary - # energy_export_price: - # unique_id: a661839f99fbc85e23d9 - # friendly_name: Energy export price - # value_template: "0.067" - # unit_of_measurement: AUD - # device_class: monetary + pvoutput_payload: + unique_id: pvoutput_payload + friendly_name: PVOutput payload + value_template: >- + d={{now().strftime("%Y%m%d")}} {#- date -#} + &t={{now().strftime("%H:%M")}} {#- time -#} + &c1=2 {#- cumulative mode -#} + &v1={{states('sensor.inverter_pv_generation_today') | int * 1000 }} {#- energy generation -#} + &v2={{states('sensor.inverter_pv_power')|float|round(0)}} {#- power generation (W) -#} + &v4={{states('sensor.inverter_load_power')|float|round(0)}} {#- power consumption (W) -#} + &v6={{states('sensor.inverter_phase_a_voltage')|float|round(1)}} {#- voltage -#} eagle_200_meter_power_demand_w: unique_id: 528a94ffdd069f6f5dcd @@ -130,288 +131,3 @@ sensor: unit_of_measurement: $/hr device_class: monetary friendly_name: Current electricity cost -# -# -# -# SunGather (used internally by ModbusTCP2MQTT add-on) produces this payload, but doesn't create sensors for everything I want to monitor: -# { -# "device_type_code": "SH5.0RS", -# "run_state": "OFF", -# "protocol_number": 1094856704, -# "protocol_version": 16781568, -# "arm_software_version": 16722, -# "dsp_software_version": 19780, -# "serial_number": 16690, -# "nominal_active_power": 5.0, -# "output_type": "2P", -# "daily_power_yields": 6.1, -# "total_power_yields": 0.0, -# "total_running_time": 0, -# "internal_temperature": 22.6, -# "total_apparent_power": 1234, -# "mppt_1_voltage": 433.4, -# "mppt_1_current": 1.2, -# "mppt_2_voltage": 213.8, -# "mppt_2_current": 0.7, -# "mppt_3_voltage": 0.0, -# "mppt_3_current": 0.0, -# "total_dc_power": 711, -# "phase_a_voltage": 243.7, -# "phase_b_voltage": 0.0, -# "phase_c_voltage": 0.0, -# "phase_a_current": 5.3, -# "phase_b_current": 0.0, -# "phase_c_current": 0.0, -# "total_active_power": 1084, -# "total_reactive_power": 509, -# "power_factor": 0.91, -# "grid_frequency": 49.97, -# "work_state_1": 0, -# "nominal_reactive_power": 3.0, -# "array_insulation_resistance": 1124, -# "active_power_regulation_setpoint": 0, -# "reactive_power_regulation_setpoint": 0, -# "work_state_2": 0, -# "meter_power": 0, -# "meter_a_phase_power": 0, -# "meter_b_phase_power": 80936959, -# "meter_c_phase_power": -65536, -# "load_power": 1084, -# "daily_export_energy": 0.1, -# "total_export_energy": 2.6, -# "daily_import_energy": 0.0, -# "total_import_energy": 192.3, -# "daily_direct_energy_consumption": 0.3, -# "total_direct_energy_consumption": 12.3, -# "daily_running_time": 0, -# "mppt_4_voltage": 0.0, -# "mppt_4_current": 0.0, -# "mppt_5_voltage": 0.0, -# "mppt_5_current": 0.0, -# "mppt_6_voltage": 0.0, -# "mppt_6_current": 0.0, -# "mppt_7_voltage": 0.0, -# "mppt_7_current": 0.0, -# "mppt_8_voltage": 0.0, -# "mppt_8_current": 0.0, -# "monthly_power_yields": 0.0, -# "mppt_9_voltage": 0.0, -# "mppt_9_current": 0.0, -# "mppt_10_voltage": 0.0, -# "mppt_10_current": 0.0, -# "mppt_11_voltage": 0.0, -# "mppt_11_current": 0.0, -# "mppt_12_voltage": 0.0, -# "mppt_12_current": 0.0, -# "negative_voltage_to_the_ground": 0.0, -# "bus_voltage": 458.0, -# "pid_work_state": 0, -# "pid_alarm_code": 0, -# "export_power": -7, -# "power_meter": 1090, -# "pv_power_of_today": 0, -# "daily_pv_energy_yields": 0.0, -# "monthly_pv_energy_yields": 0, -# "yearly_pv_energy_yields": 0.0, -# "direct_power_consumption_today_pv": 0, -# "direct_power_consumption_pv": 0.0, -# "direct_power_consumption_monthly_pv": 0.0, -# "direct_power_consumption_yearly_pv": 0.0, -# "export_power_from_pv_today": 0, -# "export_power_from_pv": 0.0, -# "export_power_from_pv_monthly": 0.0, -# "export_power_from_pv_yearly": 0.0, -# "battery_charge_power_from_pv_today": 0.0, -# "battery_charge_power_from_pv": 0.0, -# "battery_charge_power_from_pv_monthly": 0.0, -# "battery_charge_power_from_pv_yearly": 0.0, -# "string_1_current": 0.0, -# "string_2_current": 0.0, -# "string_3_current": 0.0, -# "string_4_current": 0.0, -# "string_5_current": 0.0, -# "string_6_current": 0.0, -# "string_7_current": 0.0, -# "string_8_current": 0.0, -# "string_9_current": 0.0, -# "string_10_current": 0.0, -# "string_11_current": 0.0, -# "string_12_current": 0.0, -# "string_13_current": 0.0, -# "string_14_current": 0.0, -# "string_15_current": 0.0, -# "string_16_current": 0.0, -# "string_17_current": 0.0, -# "string_18_current": 0.0, -# "string_19_current": 0.0, -# "string_20_current": 0.0, -# "string_21_current": 0.0, -# "string_22_current": 0.0, -# "string_23_current": 0.0, -# "string_24_current": 0.0, -# "system_state": 0, -# "running_state": 45, -# "daily_pv_generation": 0.3, -# "total_pv_generation": 38.5, -# "daily_pv_export": 0.0, -# "total_pv_export": 2.5, -# "load_power_hybrid": 1094, -# "export_power_hybrid": -10, -# "daily_battery_charge_from_pv": 0.0, -# "total_battery_charge_from_pv": 23.7, -# "co2_reduction": 26.9, -# "battery_voltage": 0.0, -# "battery_current": 0, -# "battery_power": 465, -# "battery_level": 5.8, -# "battery_state_of_healthy": 10.0, -# "battery_temperature": 10.8, -# "daily_battery_discharge_energy": 5.7, -# "total_battery_discharge_energy": 11.2, -# "self_consumption_of_day": 100.0, -# "grid_state": 0, -# "battery_capacity": 12.8, -# "daily_charge_energy": 0.0, -# "total_charge_energy": 10.3, -# "drm_state": 255, -# "inverter_alarm": 0.0, -# "grid-side_fault": 0.0, -# "system_fault1": 0.0, -# "system_fault2": 0.0, -# "dc-side_fault": 0.0, -# "permanent_fault": 0.0, -# "bdc-side_fault": 0.0, -# "bdc-side_permanent_fault": 0.0, -# "battery_fault": 0.0, -# "battery_alarm": 0.0, -# "bms_alarm": 0, -# "bms_protection": 0, -# "bms_fault1": 0, -# "bms_fault2": 0, -# "bms_alarm2": 0, -# "bms_status": 0, -# "max_charging_current": 0, -# "max_discharging_current": 0, -# "warning": 0, -# "protection": 0, -# "fault1": 0, -# "fault2": 0, -# "soc": 0, -# "soh": 0, -# "cycle_count": 0.0, -# "average_cell_voltage": 0, -# "max_cell_voltage": 0, -# "min_cell_voltage": 0, -# "battery_pack_voltage": 0, -# "average_cell_temp": 0, -# "max_cell_temp": 0, -# "min_cell_temp": 0, -# "start_stop": "Start", -# "power_limitation_switch": "Enable", -# "power_limitation_setting": 100.0, -# "export_power_limitation": 0, -# "export_power_limitation_value": 0, -# "current_transformer_output_current": 0, -# "current_transformer_range": 0, -# "current_transformer": 0, -# "export_power_limitation_percentage": 0.0, -# "installed_pv_power": 0.0, -# "power_factor_setting": 0.0, -# "night_svg_switch": 0, -# "reactive_power_adjustment_mode": "Enable Q(U)", -# "reactive_power_percentage_setting": 0.0, -# "power_limitation_adjustment": 0.0, -# "reactive_power_adjustment": 0.0, -# "pid_recovery": 0, -# "anti_pid": 0, -# "fullday_pid_suppression": 0, -# "export_to_grid": 0, -# "import_from_grid": 0, -# "timestamp": "2022-7-8 8:59:15" -# } -# mqtt: -# # https://github.com/bohdan-s/SunGather/blob/main/SunGather/registers-sungrow.yaml -# sensor: -# - &inverter_sensor -# state_topic: "inverter/SH50RS/registers" -# json_attributes_topic: "inverter/SH50RS/registers" -# unique_id: inverter_battery_level -# object_id: inverter_battery_level -# name: "Inverter battery level" -# value_template: "{{ value_json.battery_level }}" -# device_class: battery -# unit_of_measurement: "%" -# device: &inverter_device -# name: Solar Inverter -# manufacturer: Sungrow -# model: SH5.0RS -# via_device: 07bec9a1e7f11660c94ac9b707f6ea66 -# connections: -# - - address -# - !secret solar_inverter_ip -# - <<: *inverter_sensor -# unique_id: inverter_battery_power -# object_id: inverter_battery_power -# name: Inverter battery power -# value_template: "{{ value_json.battery_power }}" -# device_class: power -# unit_of_measurement: W -# - <<: *inverter_sensor -# unique_id: inverter_grid_current -# object_id: inverter_grid_current -# name: Inverter grid current -# value_template: "{{ value_json.phase_a_current }}" -# device_class: current -# unit_of_measurement: A -# - <<: *inverter_sensor -# unique_id: inverter_grid_voltage -# object_id: inverter_grid_voltage -# name: Inverter grid voltage -# value_template: "{{ value_json.phase_a_voltage }}" -# device_class: voltage -# unit_of_measurement: V -# - <<: *inverter_sensor -# unique_id: inverter_grid_frequency -# object_id: inverter_grid_frequency -# name: Inverter grid frequency -# value_template: "{{ value_json.grid_frequency }}" -# unit_of_measurement: Hz -# - <<: *inverter_sensor -# unique_id: inverter_total_battery_discharge -# object_id: inverter_total_battery_discharge -# name: Inverter total battery discharge -# value_template: "{{ value_json.total_battery_discharge_energy }}" -# device_class: energy -# unit_of_measurement: kWh -# state_class: total_increasing -# - <<: *inverter_sensor -# unique_id: inverter_total_battery_charge -# object_id: inverter_total_battery_charge -# name: Inverter total battery charge -# value_template: "{{ value_json.total_battery_charge_from_pv }}" -# device_class: energy -# unit_of_measurement: kWh -# state_class: total_increasing -# - <<: *inverter_sensor -# unique_id: inverter_total_pv_generation -# object_id: inverter_total_pv_generation -# name: Inverter total PV generation -# value_template: "{{ value_json.total_pv_generation }}" -# device_class: energy -# unit_of_measurement: kWh -# state_class: total_increasing -# - <<: *inverter_sensor -# unique_id: inverter_total_pv_export -# object_id: inverter_total_pv_export -# name: Inverter total PV export -# value_template: "{{ value_json.total_pv_export }}" -# device_class: energy -# unit_of_measurement: kWh -# state_class: total_increasing -# - <<: *inverter_sensor -# unique_id: inverter_pv_power -# object_id: inverter_pv_power -# name: Inverter PV power -# value_template: "{{ value_json.total_dc_power }}" -# device_class: power -# unit_of_measurement: W diff --git a/config/packages/grow.yaml b/config/packages/grow.yaml index 4fbbda8..7d19d20 100644 --- a/config/packages/grow.yaml +++ b/config/packages/grow.yaml @@ -1,62 +1,54 @@ -android_ip_webcam: - - host: 10.10.10.112 - name: Tent Cam - sensors: - - battery_level - - battery_temp - - light - - proximity - switches: - - exposure_lock - - ffc - - focus - - night_vision - - overlay - camera: - platform: mjpeg_timelapse image_url: http://10.10.10.112:8080/shot.jpg name: Tent Timelapse fetch_interval: 3600 - max_frames: 36 - framerate: 10 + max_frames: 1000 + framerate: 5 quality: 80 loop: true + # - platform: mjpeg_timelapse + # image_url: http://10.10.10.112:8080/shot.jpg + # name: Tent Timelapse (Daily, ) + # fetch_interval: + # max_frames: 365 + # framerate: 10 + # quality: 80 + # loop: true + +sensor: + - platform: schedule_state + name: Tent light schedule template: - binary_sensor: - unique_id: tent_lights_status name: Tent lights status - delay_on: "0:00:05" - delay_off: "0:00:05" state: | - {{ states('sensor.tent_wattage') | float > 150 }} - attributes: - device_class: power + {{ 500 < [states('sensor.ble_illuminance_tent_c47c8d6dd13f') | int(default=0), states('sensor.ble_illuminance_tent_c47c8d6dd155') | int(default=0)] | max }} + # trigger: + # - platform: numeric_state + # entity_id: + # # - sensor.ble_illuminance_tent_c47c8d6dd155 + # - sensor.ble_illuminance_tent_c47c8d6dd13f + # below: 700 + # variables: + # state: false + # - platform: numeric_state + # entity_id: + # # - sensor.ble_illuminance_tent_c47c8d6dd155 + # - sensor.ble_illuminance_tent_c47c8d6dd13f + # above: 700 + # variables: + # state: true - sensor: - - unique_id: tent_temperature_cached - name: Tent Temperature (cached) - unit_of_measurement: °C - device_class: temperature - state_class: measurement - state: | - {{ float(states('sensor.tent_temperature'), default=states('sensor.tent_temperature_cached')) }} - - - unique_id: tent_humidity_cached - name: Tent Humidity (cached) - unit_of_measurement: "%" - device_class: humidity - state_class: measurement - state: | - {{ float(states('sensor.tent_humidity'), default=states('tent_humidity_cached')) }} - - unique_id: tent_svp name: "Tent SVP (Saturation Vapor Pressure)" unit_of_measurement: kPa device_class: pressure state_class: measurement state: | - {% set T = float(states('sensor.tent_temperature_cached')) %} + {% set T = float(states('sensor.ble_temperature_tent_a4c1385ec751')) %} {% if is_number(T) %} {{ (0.61078 * e ** (17.2694 * T / (T + 238.3))) | round(3) }} {% else %} @@ -69,7 +61,7 @@ template: state_class: measurement state: | {% set SVP = float(states('sensor.tent_svp')) %} - {% set RH = float(states('sensor.tent_humidity_cached')) %} + {% set RH = float(states('sensor.ble_humidity_tent_a4c1385ec751')) %} {% if is_number(SVP) and is_number(RH) %} {{ (SVP * (RH/100.0)) | round(3) }} {% else %} @@ -90,6 +82,20 @@ template: {% endif %} automation: + - id: snapshot_camera + alias: Snapshot grow camera every 12 hours + trigger: + - platform: time_pattern + hours: "/12" + condition: + - "{{ is_state('binary_sensor.tent_lights_status', 'on') }}" + action: + - service: camera.snapshot + target: + entity_id: camera.tent_camera_mjpeg + data_template: + filename: "/config/camera/camera.tent_camera_mjpeg/{{ now().strftime('%Y%m%d-%H%M%S') }}.jpg" + - id: "1635395611631" alias: Tent Cam Night Mode When Light Is Off description: "" @@ -297,9 +303,7 @@ automation: condition: - condition: or conditions: - - condition: numeric_state - entity_id: sensor.tent_wattage - below: "150" + - "{{ is_state('binary_sensor.tent_lights_status', 'off') }}" - condition: numeric_state entity_id: sensor.tent_humidity_cached above: input_number.minimum_tent_humidity @@ -311,33 +315,6 @@ automation: - switch.tent_humidifier - switch.tent_humidifier_local mode: restart - - id: "1644716285765" - alias: Re-focus tent cam regularly - description: "" - trigger: - - platform: time_pattern - minutes: /5 - seconds: "0" - hours: "*" - condition: - - condition: numeric_state - entity_id: sensor.tent_wattage - above: "150" - action: - - service: switch.toggle - data: {} - target: - entity_id: switch.tent_cam_focus - - delay: - hours: 0 - minutes: 0 - seconds: 3 - milliseconds: 0 - - service: switch.toggle - data: {} - target: - entity_id: switch.tent_cam_focus - mode: single - id: "1645058611536" alias: Count humidifier run time description: "" @@ -382,38 +359,28 @@ automation: target: entity_id: timer.humidifier_time_till_refill mode: restart - - id: "1647038709985" - alias: Disable timelapse when lights off - description: "" + + - id: "b30ad63e38bec67a0207" + alias: Timelapse tent cam only when tent lights on trigger: - - platform: numeric_state - entity_id: sensor.tent_wattage - for: - hours: 0 - minutes: 0 - seconds: 30 - below: "100" + - platform: state + entity_id: binary_sensor.tent_lights_status + not_to: + - unknown + - unavailable + not_from: + - unknown + - unavailable + variables: + service: > + {% if trigger.to_state.state == 'on' %} + mjpeg_timelapse.resume_recording + {% else %} + mjpeg_timelapse.pause_recording + {% endif %} condition: [] action: - - service: mjpeg_timelapse.pause_recording - data: {} - target: - entity_id: camera.tent_timelapse - mode: single - - id: "1647038771614" - alias: Enable timelapse when lights on - description: "" - trigger: - - platform: numeric_state - entity_id: sensor.tent_wattage - for: - hours: 0 - minutes: 15 - seconds: 0 - above: "180" - condition: [] - action: - - service: mjpeg_timelapse.resume_recording + - service: "{{ service }}" data: {} target: entity_id: camera.tent_timelapse diff --git a/config/packages/home.yaml b/config/packages/home.yaml index 8469f37..ba8a0e2 100644 --- a/config/packages/home.yaml +++ b/config/packages/home.yaml @@ -52,7 +52,17 @@ automation: action: - service: light.turn_off target: - entity_id: all + area_id: + - ri_s_office + - bo_s_office + - living_room + - kitchen + - hallway + - laundry_room + - bathroom + - analog_room + - outdoors + - garden_shed - service: light.turn_on data: color_temp: 462 @@ -117,6 +127,57 @@ automation: data: entity_id: "{{ toggle }}" + - id: bedroom_blinds + alias: Manage bedroom blinds + trigger: + - platform: state + entity_id: binary_sensor.in_bed + to: "on" + id: in_bed + for: + hours: 2 # proxy for "is asleep" + - id: sunset + platform: state + entity_id: sun.sun + to: below_horizon + action: + - service: cover.close_cover + target: + area_id: bedroom + # if we've gone to bed, wait for the us to get up or 8 hours to pass (whichever happens first) to then re-open + # blinds. + - choose: + - conditions: + condition: trigger + id: in_bed + sequence: + - wait_for_trigger: + - platform: template + value_template: > + {{ is_state('binary_sensor.in_bed', 'off') }} + for: + minutes: 10 # _staying_ out of bed + timeout: + hours: 6 # 2 hours already part of trigger condition, for 8 hours total + - wait_for_trigger: + - platform: template + value_template: > + {{ is_state('sun.sun', 'above_horizon') and now().hour >= 7 }} + - service: cover.set_cover_position + data: + position: 20 + target: + area_id: bedroom + - wait_for_trigger: + - platform: template + value_template: > + {{ is_state('binary_sensor.anyone_in_bed', 'off') }} + timeout: + hours: 2 + - service: cover.open_cover + target: + area_id: bedroom + template: - binary_sensor: - unique_id: in_bed @@ -166,7 +227,15 @@ homekit: - switch.bos_office_heater - switch.ri_s_desk_plug + - cover.analog_room_blinds + - cover.bos_office_blinds + - cover.bedroom_blinds + - cover.front_gate + - climate.living_room_a_c + - light.fairy_lights + include_entity_globs: + - climate.living_room* - binary_sensor.*_is_occupied - binary_sensor.*_motion - binary_sensor.*_presence @@ -190,6 +259,23 @@ homekit: - sensor.*weather* - sensor.nas_* - sensor.*_nas_* + + # Magic areas entities + - light.area_* + - light.sleep_lights_* + - light.global_lights + - light.interior_lights + - light.exterior_lights + - light.overhead_lights* + - light.accent_lights* + - cover.area_* + - switch.area_light_control_* + - binary_sensor.area_battery_* + - binary_sensor.area_connectivity_* + - binary_sensor.area_door_* + - binary_sensor.area_tamper_* + - binary_sensor.area_update_* + - binary_sensor.area_global exclude_domains: [] entity_config: vacuum.robot_vacuum: diff --git a/config/packages/media_centre.yaml b/config/packages/media_centre.yaml index a8893d5..83c4860 100644 --- a/config/packages/media_centre.yaml +++ b/config/packages/media_centre.yaml @@ -151,6 +151,9 @@ template: {{- sources | sort | unique | list -}} media_player: + - platform: denon + host: 10.10.20.77 + - platform: universal name: Living Room Spotify (bjeanes) # create a media player that is only "on"/"playing"/etc when it is playing in the living room children: @@ -351,7 +354,7 @@ sensor: refresh: "5:00:00" default_state: "off" events: - - state: PBS # Default background music + - state: PBS 106.7FM Melbourne # Default background music start: "8:00:00" end: "21:00:00" @@ -369,6 +372,13 @@ sensor: condition: time weekday: [sun] + - state: Ten FM # Dad's show + start: "9:00:00" + end: "12:00:00" + condition: + condition: time + weekday: [sun] + - state: KLFM start: "12:00:00" end: "15:00:00" @@ -388,7 +398,7 @@ sensor: entity_id: sensor.rrr_now_playing state: "Stylin'" - - state: PBS + - state: PBS 106.7FM Melbourne condition: condition: state entity_id: sensor.pbs_now_playing diff --git a/config/packages/media_server.yaml b/config/packages/media_server.yaml index 1fd2b92..de69d98 100644 --- a/config/packages/media_server.yaml +++ b/config/packages/media_server.yaml @@ -9,15 +9,3 @@ template: {% else %} {{ states('sensor.nzbget_speed') }} {% endif %} - -sensor: - - platform: rtorrent - url: !secret rtorrent_url - monitored_variables: - - "current_status" - - "download_speed" - - "upload_speed" - - "all_torrents" - - "uploading_torrents" - - "downloading_torrents" - - "active_torrents" diff --git a/config/packages/offices.yaml b/config/packages/offices.yaml index c89168a..e86a710 100644 --- a/config/packages/offices.yaml +++ b/config/packages/offices.yaml @@ -1,3 +1,13 @@ +input_number: + bo_s_office_target_temperature: + name: Bo's Office target temperature + min: 18 + max: 24 + step: 0.2 + unit_of_measurement: "°C" + initial: 21 + mode: box + # If door opens when sun is down, turn lights on # If sun sets and door is open or presense detected, turn lights on # If lights on but no presence for one hour, turn lights off @@ -40,14 +50,14 @@ automation: {{ is_state('binary_sensor.bo_s_office_door_contact', 'off') and (is_state('binary_sensor.bo_s_office_motion', 'on') or is_state('binary_sensor.bo_s_office_is_occupied', 'on')) - and states('sensor.ble_temperature_bos_office_a4c1380f0b98') | float < 19 }} + and states('sensor.ble_temperature_bos_office_a4c1380f0b98') | float < states('input_number.bo_s_office_target_temperature') | float }} variables: service: switch.turn_on - platform: template value_template: | {{ is_state('binary_sensor.bo_s_office_door_contact', 'on') or (is_state('binary_sensor.bo_s_office_motion', 'off') and is_state('binary_sensor.bo_s_office_is_occupied', 'off')) - or states('sensor.ble_temperature_bos_office_a4c1380f0b98') | float > 20 }} + or states('sensor.ble_temperature_bos_office_a4c1380f0b98') | float >= states('input_number.bo_s_office_target_temperature') | float }} variables: service: switch.turn_off action: diff --git a/config/packages/optimise_solar.yaml b/config/packages/optimise_solar.yaml new file mode 100644 index 0000000..de289d8 --- /dev/null +++ b/config/packages/optimise_solar.yaml @@ -0,0 +1,359 @@ +automation: + # The inverter can only generate 5kW of AC power. IFF the battery is not-full, it can generate 5kW of AC _and_ charge + # battery at up to 6.6kW, which saturates our 8.46 kW of PV + # + # So, preventing the battery from getting full too early on a sunny day will increase our overall yield, because the + # inverter won't have to derate the PV power to 5kW. + # + # [1]: https://discord.com/channels/936031869001158666/1008992991643455529 + # [2]: https://discord.com/channels/936031869001158666/936031869001158669/1011882768021590036 + - id: 05bdc8eb58714c26c2fe + alias: Inverter - maximise output + mode: restart + trigger: + - platform: state + entity_id: + - sensor.inverter_pv_power + - sensor.inverter_battery_level + - sensor.inverter_active_power + - sensor.home_weather_cloud_coverage + - sensor.home_weather_forecast_cloud_coverage + - sensor.solcast_forecast_today + - sensor.solcast_forecast_this_hour + - sensor.solcast_forecast_remaining_today + # - sensor.home_weather_forecast_condition + - sensor.home_weather_condition + # - weather.home + - weather.home_hourly # can use attributes on this one to make decisions about the coming hours + # - weather.home_weather + - sun.sun # use `next_setting` attribute to ensure battery is online at least an hour before sunset + not_to: + - unavailable + - unknown + variables: + # Magic numbers + ems_self_consume: 0 + ems_forced: 2 + battery_charge: 0xAA + battery_discharge: 0xBB + battery_stop: 0xCC + active_power_limit: 4999 # W + active_power_buffer: 400 # W - how much below limit we want to sit + battery_upper_limit: 99.5 # % - above this, let the BMS choose the charge rate + battery_capacity: 12.8 # kWh + + # Shorthands + current_active_power: "{{ states('sensor.inverter_active_power') | int(default=active_power_limit) }}" + current_pv_power: "{{ states('sensor.inverter_pv_power') | int(default=0) }}" + current_load_power: "{{ states('sensor.inverter_load_power') | int(default=current_pv_power) }}" + current_ems_mode: "{{ states('sensor.inverter_ems_mode_raw') | int(default=-1) }}" + current_battery_mode: "{{ states('sensor.inverter_forced_battery_mode_raw') | int(default=0) }}" + battery_level: "{{ states('sensor.inverter_battery_level') | float(default=100) }}" + forced_battery_power: "{{ states('sensor.inverter_battery_forced_charge_discharge_power') | int(default=0) }}" + forecast_total: "{{ states('sensor.solcast_forecast_today') | float(default=0) }}" + forecast_remaining: "{{ states('sensor.solcast_forecast_remaining_today') | float(default=0) }}" + forecast_hour: "{{ states('sensor.solcast_forecast_this_hour') | float(default=0) / 1000.0 }}" + forecast_remaining_pessimistic: "{{ [0, forecast_remaining - forecast_hour] | max }}" + # battery_lower_limit: > + # {% if is_state('sensor.home_weather_condition', 'sunny') %} + # {{ 10 }} + # {% elif is_state('sensor.home_weather_condition', 'partlycloudy') %} + # {{ 20 }} + # {% else %} + # {{ 70 }} + # {% endif %} + battery_lower_limit: 10 # ignoring above as weather forecast is too unreliable anyway + target_active_power: "{{ active_power_limit - active_power_buffer }}" + # TODO: make this scale proportionally to how far it is from target battery charge. + desired_forced_battery_power: > + {% if current_pv_power > target_active_power %} + {{ current_pv_power - target_active_power }} + {% else %} + 10 + {% endif %} + is_forced_charging: > + {{ current_ems_mode == ems_forced and current_battery_mode == battery_charge }} + is_forced_discharging: > + {{ current_ems_mode == ems_forced and current_battery_mode == battery_discharge }} + is_self_consuming: > + {{ current_ems_mode == ems_self_consume }} + kwh_until_full: > + {{ battery_capacity * ((100 - battery_level)/100) }} + enough_in_day: > + {{ 2.5 * kwh_until_full < forecast_remaining_pessimistic }} + generating_more_than_usage: > + {{ current_pv_power > (1.5 * current_load_power) }} + # target_battery_level: > + # {{ [[battery_lower_limit, 100.0 * (1.0 - (forecast_remaining_pessimistic/forecast_total)) | round(2)] | max, 100] | min }} + target_battery_level: > + {% if enough_in_day %} + {{ [battery_level - 10, states('input_number.inverter_battery_reserve') | int + 5] | max }} + {% else %} + {{ [battery_level, states('input_number.inverter_battery_reserve') | int + 5] | max }} + {% endif %} + battery_high_enough: "{{ battery_level >= target_battery_level }}" + battery_too_high: "{{ battery_level >= battery_upper_limit }}" + sunsetting: > + {{ now() + timedelta(hours = 2) > state_attr('sun.sun', 'next_setting') | as_datetime }} + should_slow_battery: > + {{ + not sunsetting + and enough_in_day + and generating_more_than_usage + and battery_high_enough + and not battery_too_high + }} + should_discharge_battery: > + {{ should_slow_battery + and current_pv_power < (target_active_power - 500) + and battery_level < 92 + }} + target_discharge_power: > + {{ [10, ((target_active_power - 500) - current_pv_power) | int] | max }} + action: + # TODO: discharge battery if too high and PV has dropped while forecast remains high + - choose: + - conditions: + - "{{ should_discharge_battery }}" + sequence: + - service: input_number.set_value + target: + entity_id: input_number.inverter_forced_mode_battery_power + data_template: + value: "{{ target_discharge_power }}" + - condition: "{{ not is_forced_discharging }}" + - service: script.inverter_force_battery_discharge + - conditions: + - "{{ should_slow_battery }}" + sequence: + - service: input_number.set_value + target: + entity_id: input_number.inverter_forced_mode_battery_power + data_template: + value: "{{ desired_forced_battery_power }}" + - condition: "{{ not is_forced_charging }}" + - service: script.inverter_force_battery_charge + - conditions: + - not: + - "{{ is_self_consuming }}" + sequence: + - service: script.inverter_self_consumption + default: [] + + - id: d5fa94e6-772a-4903-882a-4ed8cfd7854e + alias: Inverter - maximise output (new) + mode: restart + trigger: + - platform: state + entity_id: + - sensor.inverter_pv_power + - sensor.inverter_battery_level + - sensor.inverter_active_power + - sensor.home_weather_cloud_coverage + - sensor.home_weather_forecast_cloud_coverage + - sensor.solcast_forecast_today + - sensor.solcast_forecast_this_hour + - sensor.solcast_forecast_remaining_today + # - sensor.home_weather_forecast_condition + - sensor.home_weather_condition + # - weather.home + - weather.home_hourly # can use attributes on this one to make decisions about the coming hours + # - weather.home_weather + - sun.sun # use `next_setting` attribute to ensure battery is online at least an hour before sunset + not_to: + - unavailable + - unknown + variables: + # Magic numbers + ems_self_consume: 0 + ems_forced: 2 + battery_charge: 0xAA + battery_discharge: 0xBB + battery_stop: 0xCC + active_power_limit: 4999 # W + active_power_buffer: 400 # W - how much below limit we want to sit + battery_upper_limit: 99.5 # % - above this, let the BMS choose the charge rate + battery_capacity: 12.8 # kWh + + # Shorthands + current_active_power: "{{ states('sensor.inverter_active_power') | int(default=active_power_limit) }}" + current_pv_power: "{{ states('sensor.inverter_pv_power') | int(default=0) }}" + current_load_power: "{{ states('sensor.inverter_load_power') | int(default=current_pv_power) }}" + current_ems_mode: "{{ states('sensor.inverter_ems_mode_raw') | int(default=-1) }}" + current_battery_mode: "{{ states('sensor.inverter_forced_battery_mode_raw') | int(default=0) }}" + battery_level: "{{ states('sensor.inverter_battery_level') | float(default=100) }}" + forced_battery_power: "{{ states('sensor.inverter_battery_forced_charge_discharge_power') | int(default=0) }}" + forecast_total: "{{ states('sensor.solcast_forecast_today') | float(default=0) }}" + forecast_remaining: "{{ states('sensor.solcast_forecast_remaining_today') | float(default=0) }}" + forecast_hour: "{{ states('sensor.solcast_forecast_this_hour') | float(default=0) / 1000.0 }}" + forecast_remaining_pessimistic: "{{ [0, forecast_remaining - forecast_hour] | max }}" + # battery_lower_limit: > + # {% if is_state('sensor.home_weather_condition', 'sunny') %} + # {{ 10 }} + # {% elif is_state('sensor.home_weather_condition', 'partlycloudy') %} + # {{ 20 }} + # {% else %} + # {{ 70 }} + # {% endif %} + battery_lower_limit: 10 # ignoring above as weather forecast is too unreliable anyway + target_active_power: "{{ active_power_limit - active_power_buffer }}" + # TODO: make this scale proportionally to how far it is from target battery charge. + desired_forced_battery_power: > + {% if current_pv_power > target_active_power %} + {{ current_pv_power - target_active_power }} + {% else %} + 10 + {% endif %} + is_forced_charging: > + {{ current_ems_mode == ems_forced and current_battery_mode == battery_charge }} + is_forced_discharging: > + {{ current_ems_mode == ems_forced and current_battery_mode == battery_discharge }} + is_self_consuming: > + {{ current_ems_mode == ems_self_consume }} + kwh_until_full: > + {{ battery_capacity * ((100 - battery_level)/100) }} + enough_in_day: > + {{ 2.5 * kwh_until_full < forecast_remaining_pessimistic }} + generating_more_than_usage: > + {{ current_pv_power > (1.5 * current_load_power) }} + # target_battery_level: > + # {{ [[battery_lower_limit, 100.0 * (1.0 - (forecast_remaining_pessimistic/forecast_total)) | round(2)] | max, 100] | min }} + target_battery_level: > + {% if enough_in_day %} + {{ battery_level - 10 }} + {% else %} + {{ battery_level }} + {% endif %} + battery_high_enough: "{{ battery_level >= target_battery_level }}" + battery_too_high: "{{ battery_level >= battery_upper_limit }}" + sunsetting: > + {{ now() + timedelta(hours = 2) > state_attr('sun.sun', 'next_setting') | as_datetime }} + should_slow_battery: > + {{ + not sunsetting + and enough_in_day + and generating_more_than_usage + and battery_high_enough + and not battery_too_high + }} + target_discharge_power: > + {% if (battery_level - target_battery_level) > 1 %} + {{ [6000, (battery_level - target_battery_level) * 1000 | int] | min }} + {% else %} + 100 + {% endif %} + action: + # TODO: discharge battery if too high and PV has dropped while forecast remains high + - choose: + - conditions: + - "{{ should_slow_battery }}" + sequence: + - service: input_number.set_value + target: + entity_id: input_number.inverter_forced_mode_battery_power + data_template: + value: "{{ target_discharge_power }}" + - condition: "{{ not is_forced_discharging }}" + - service: script.inverter_force_battery_discharge + - conditions: + - not: + - "{{ is_self_consuming }}" + sequence: + - service: script.inverter_self_consumption + default: [] + +template: + - sensor: + - unique_id: e1152f05-57d8-4821-b8fc-d6bca771a3b5 + name: Inverter target active power + unit_of_measurement: W + state_class: measurement + device_class: power + attributes: + solar: "true" + state: >- + {{ 4999 - states('input_number.inverter_active_power_buffer') | int(default=400) }} + + - unique_id: a59d08fc-92bb-47c6-b015-8ed0e475f2e5 + name: Inverter desired forced battery power + unit_of_measurement: W + state_class: measurement + device_class: power + attributes: + solar: "true" + state: >- + {% set current_pv_power = states('sensor.inverter_pv_power') | int(default=0) %} + {% set target_active_power = states('sensor.inverter_target_active_power') | int %} + + {% if current_pv_power > target_active_power %} + {{ current_pv_power - target_active_power }} + {% else %} + 10 + {% endif %} + + - unique_id: d257272c-3ac0-4d93-9ef7-00717757cef3 + name: Solar forecast remaining pessimistic + state_class: measurement + device_class: energy + unit_of_measurement: kWh + attributes: + solar: "true" + state: >- + {% set forecast_remaining = states('sensor.solcast_forecast_remaining_today') | float(default=0) %} + {% set forecast_hour = states('sensor.solcast_forecast_this_hour') | float(default=0) / 1000.0 %} + {{ [0, forecast_remaining - forecast_hour] | max }} + + - unique_id: 6bf7ad20-cf6a-4689-8214-13cd63de80a9 + name: Inverter target battery level + state_class: measurement + unit_of_measurement: "%" + attributes: + solar: "true" + state: >- + {% set battery_lower_limit = states('input_number.inverter_battery_reserve') | int + 5 %} + {% set forecast_remaining_pessimistic = states('sensor.solar_forecast_remaining_pessimistic') | float(default=0) %} + {% set forecast_total = states('sensor.solcast_forecast_today') | float(default=0) %} + {{ [[battery_lower_limit, 100.0 * (1.0 - (forecast_remaining_pessimistic/forecast_total)) | round(2)] | max, 100] | min }} + + - unique_id: f603d8f8-92ce-4e77-b271-048110394658 + name: Inverter battery mode + attributes: + solar: "true" + icon: >- + {% if this.state == 'self-consumption' %} + mdi:battery-sync + {% elif this.state == 'forced charging' %} + mdi:battery-arrow-down + {% elif this.state == 'forced discharging' %} + mdi:battery-arrow-up + {% elif this.state == 'forced stop' %} + mdi:battery-off + {% endif %} + + state: >- + {% set ems = states('sensor.inverter_ems_mode_raw') | int(default=-1) %} + {% set mode = states('sensor.inverter_forced_battery_mode_raw') | int(default=0) %} + {% if ems == 0 %} + self-consumption + {% elif ems == 2 %} + {% if mode == 0xAA %} + forced charging + {% elif mode == 0xBB %} + forced discharging + {% elif mode == 0xCC %} + forced stop + {% else %} + unknown + {% endif %} + {% else %} + unknown + {% endif %} + +input_number: + inverter_active_power_buffer: + name: Inverter active power buffer + min: 100 + max: 1000 + step: 1 + unit_of_measurement: W + mode: box diff --git a/config/packages/presence.yaml b/config/packages/presence.yaml index 76d8a4e..a4a6e27 100644 --- a/config/packages/presence.yaml +++ b/config/packages/presence.yaml @@ -202,7 +202,7 @@ template: device_class: occupancy - unique_id: analog_room_is_occupied - name: analog Room Is Occupied + name: analog Room As Occupied state: | {{ is_state('sensor.template_room_bo_phone', 'analog_room') or is_state('sensor.template_room_ri_phone', 'analog_room') }} icon: | diff --git a/config/packages/sungrow.yaml b/config/packages/sungrow.yaml index e6f713e..064661c 100644 --- a/config/packages/sungrow.yaml +++ b/config/packages/sungrow.yaml @@ -30,48 +30,39 @@ input_boolean: inverter_charging_schedule_enabled: - initial: true name: Inverter charging schedule enabled inverter_charging_schedule_2_enabled: - initial: true name: Inverter charging schedule 2 enabled input_datetime: inverter_charging_schedule_start: has_time: true name: Inverter charging schedule start - initial: "13:30:00" inverter_charging_schedule_end: has_time: true name: Inverter charging schedule end - initial: "15:00:00" inverter_charging_schedule_2_start: has_time: true name: Inverter charging schedule 2 start - initial: "00:00:00" inverter_charging_schedule_2_end: has_time: true name: Inverter charging schedule 2 end - initial: "00:00:00" input_number: inverter_charging_schedule_target_soc: name: Inverter charging schedule target state of charge min: 0 max: 100 unit_of_measurement: "%" - initial: 85 mode: box inverter_charging_schedule_2_target_soc: name: Inverter charging schedule 2 target state of charge min: 0 max: 100 unit_of_measurement: "%" - initial: 0 mode: box inverter_battery_reserve: name: Inverter battery reserve min: 0 max: 100 - initial: 5 unit_of_measurement: "%" mode: box @@ -80,7 +71,6 @@ input_number: min: 10 max: 6600 step: 10 - initial: 2000 mode: box unit_of_measurement: "W" @@ -199,7 +189,7 @@ automation: variables: current_power: "{{ states('sensor.inverter_battery_forced_charge_discharge_power') | int }}" target_power: "{{ states('input_number.inverter_forced_mode_battery_power') | int }}" - target_power_value: "{{ target_power / 10 }}" # undocumented register is in multiples of 10W + target_power_value: "{{ (target_power / 10) | round(0) | int }}" # undocumented register is in multiples of 10W condition: - "{{ current_power != target_power }}" action: @@ -235,98 +225,6 @@ automation: data_template: value: "{{ states('sensor.inverter_battery_forced_charge_discharge_power') | int }}" - # The inverter can only generate 5kW of AC power. IFF the battery is not-full, it can generate 5kW of AC _and_ charge - # battery at up to 6.6kW, which saturates our 8.46 kW of PV - # - # So, preventing the battery from getting full too early on a sunny day will increase our overall yield, because the - # inverter won't have to derate the PV power to 5kW. - # - # [1]: https://discord.com/channels/936031869001158666/1008992991643455529 - # [2]: https://discord.com/channels/936031869001158666/936031869001158669/1011882768021590036 - - id: 05bdc8eb58714c26c2fe - alias: Inverter - maximise output - mode: restart - trigger: - - platform: state - entity_id: - - sensor.inverter_pv_power - - sensor.inverter_battery_level - - sensor.inverter_active_power - - sensor.home_weather_cloud_coverage - - sensor.home_weather_forecast_cloud_coverage - - sensor.solcast_forecast_remaining_today - # - sensor.home_weather_forecast_condition - # - sensor.home_weather_condition - # - weather.home - - weather.home_hourly # can use attributes on this one to make decisions about the coming hours - # - weather.home_weather - - sun.sun # use `next_setting` attribute to ensure battery is online at least an hour before sunset - not_to: - - unavailable - - unknown - variables: - # Magic numbers - ems_self_consume: 0 - ems_forced: 2 - battery_charge: 0xAA - battery_discharge: 0xBB - battery_stop: 0xCC - active_power_limit: 4999 # W - active_power_buffer: 200 # W - how much below limit we want to sit - battery_lower_limit: 50 # % - battery_upper_limit: 98 # % - above this, let the BMS choose the charge rate - battery_capacity: 12.8 # kWh - - # Shorthands - current_active_power: "{{ states('sensor.inverter_active_power') | int(default=active_power_limit) }}" - current_pv_power: "{{ states('sensor.inverter_pv_power') | int(default=0) }}" - current_ems_mode: "{{ states('sensor.inverter_ems_mode_raw') | int(default=-1) }}" - current_battery_mode: "{{ states('sensor.inverter_forced_battery_mode_raw') | int(default=0) }}" - battery_level: "{{ states('sensor.inverter_battery_level') | float(default=100) }}" - forced_battery_power: "{{ states('sensor.inverter_battery_forced_charge_discharge_power') | int(default=0) }}" - forecast_remaining: "{{ states('sensor.solcast_forecast_remaining_today') | float(default=0) }}" - - target_active_power: "{{ active_power_limit - active_power_buffer }}" - desired_forced_battery_power: > - {% if current_pv_power > target_active_power %} - {{ current_pv_power - target_active_power }} - {% else %} - 10 - {% endif %} - is_forced_charging: > - {{ current_ems_mode == ems_forced and current_battery_mode == battery_charge }} - is_self_consuming: > - {{ current_ems_mode == ems_self_consume }} - kwh_until_full: > - {{ battery_capacity * ((100 - battery_level)/100) }} - enough_in_day: > - {{ 2.5 * kwh_until_full < forecast_remaining }} - battery_high_enough: "{{ battery_level > battery_lower_limit }}" - battery_too_high: "{{ battery_level >= battery_upper_limit }}" - sunsetting: > - {{ now() + timedelta(hours = 1) > state_attr('sun.sun', 'next_setting') | as_datetime }} - should_slow_battery: > - {{ not sunsetting and battery_high_enough and enough_in_day and not battery_too_high }} - action: - # TODO: discharge battery if too high and PV has dropped while forecast remains high - - choose: - - conditions: - - "{{ should_slow_battery }}" - sequence: - - service: input_number.set_value - target: - entity_id: input_number.inverter_forced_mode_battery_power - data_template: - value: "{{ desired_forced_battery_power }}" - - condition: "{{ is_self_consuming or not is_forced_charging }}" - - service: script.inverter_force_battery_charge - - conditions: - - not: - - "{{ is_self_consuming }}" - sequence: - - service: script.inverter_self_consumption - default: [] - script: inverter_set_battery_reserve: alias: "Set inverter battery reserve" @@ -1395,21 +1293,18 @@ sensor: # input_number: # set_sg_min_soc: # name: min Soc -# #initial: 15 # min: 5 # max: 50 # step: 1 # set_sg_max_soc: # name: max Soc -# #initial: 85 # min: 50 # max: 95 # step: 1 # set_sg_charge_discharge_power_percentage: # name: max charge discharge power in W -# #initial: 40 # min: 0 # max: 5000 # step: 50 diff --git a/config/packages/work.yaml b/config/packages/work.yaml index 826dd54..7f5431f 100644 --- a/config/packages/work.yaml +++ b/config/packages/work.yaml @@ -11,6 +11,8 @@ automation: trigger: - platform: state entity_id: cover.front_gate + for: + seconds: 2 from: "closed" to: - open diff --git a/esphome/athom-plug-5586a8.yaml b/esphome/athom-plug-5586a8.yaml index 893b158..4bdbc31 100644 --- a/esphome/athom-plug-5586a8.yaml +++ b/esphome/athom-plug-5586a8.yaml @@ -1,6 +1,6 @@ substitutions: node_name: "athom-plug-5586a8" - friendly_name: "Tent Plug" + friendly_name: "Garden Shed Lights" packages: base: !include common/base.yaml diff --git a/esphome/athom-smart-plug-v2-3fe952.yaml b/esphome/athom-smart-plug-v2-3fe952.yaml new file mode 100644 index 0000000..d1c0e90 --- /dev/null +++ b/esphome/athom-smart-plug-v2-3fe952.yaml @@ -0,0 +1,12 @@ +substitutions: + name: athom-smart-plug-v2-3fe952 +packages: + athom.smart-plug-v2: github://athom-tech/athom-configs/athom-smart-plug-v2.yaml +esphome: + name: ${name} + name_add_mac_suffix: false + + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password diff --git a/esphome/athom-smart-plug-v2-3feb8a.yaml b/esphome/athom-smart-plug-v2-3feb8a.yaml new file mode 100644 index 0000000..216535a --- /dev/null +++ b/esphome/athom-smart-plug-v2-3feb8a.yaml @@ -0,0 +1,12 @@ +substitutions: + name: athom-smart-plug-v2-3feb8a +packages: + athom.smart-plug-v2: github://athom-tech/athom-configs/athom-smart-plug-v2.yaml +esphome: + name: ${name} + name_add_mac_suffix: false + + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password diff --git a/esphome/athom-smart-plug-v2-3fee17.yaml b/esphome/athom-smart-plug-v2-3fee17.yaml new file mode 100644 index 0000000..2fade92 --- /dev/null +++ b/esphome/athom-smart-plug-v2-3fee17.yaml @@ -0,0 +1,7 @@ +substitutions: + node_name: "athom-smart-plug-v2-3fee17" + # friendly_name: "Tent Plug" + +packages: + base: !include common/base.yaml + plug: !include common/athom-plug.yaml \ No newline at end of file diff --git a/esphome/athom-smart-plug-v2-3fee1c.yaml b/esphome/athom-smart-plug-v2-3fee1c.yaml new file mode 100644 index 0000000..cc57a50 --- /dev/null +++ b/esphome/athom-smart-plug-v2-3fee1c.yaml @@ -0,0 +1,12 @@ +substitutions: + name: athom-smart-plug-v2-3fee1c +packages: + athom.smart-plug-v2: github://athom-tech/athom-configs/athom-smart-plug-v2.yaml +esphome: + name: ${name} + name_add_mac_suffix: false + + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password diff --git a/esphome/athom-smart-plug-v2-3ff29b.yaml b/esphome/athom-smart-plug-v2-3ff29b.yaml new file mode 100644 index 0000000..f939625 --- /dev/null +++ b/esphome/athom-smart-plug-v2-3ff29b.yaml @@ -0,0 +1,12 @@ +substitutions: + name: athom-smart-plug-v2-3ff29b +packages: + athom.smart-plug-v2: github://athom-tech/athom-configs/athom-smart-plug-v2.yaml +esphome: + name: ${name} + name_add_mac_suffix: false + + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password diff --git a/esphome/ble-gateway-2.yaml b/esphome/ble-gateway-2.yaml index 68ac0da..6ca09df 100644 --- a/esphome/ble-gateway-2.yaml +++ b/esphome/ble-gateway-2.yaml @@ -9,205 +9,11 @@ esphome: packages: base: !include common/base.yaml ble: !include common/ble-gateway.yaml - + # ph_260bd: !include common/ph_260bd.yaml + web_server: version: 2 include_internal: true wifi: use_address: 10.10.30.82 - -# JDY-08 -# https://amperkot.ru/static/3236/uploads/datasheets/JDY-08.pdf -# [13:44:48][I][ble_client:085]: Attempting BLE connection to 7c:01:0a:43:4e:9e -# [13:44:49][D][ble_client_lambda:035]: Connected to BLE device -# [13:44:49][I][ble_client:161]: Service UUID: 0xFFE0 -# [13:44:49][I][ble_client:162]: start_handle: 0x1 end_handle: 0x9 -# [13:44:49][I][ble_client:341]: characteristic 0xFFE1, handle 0x3, properties 0x1c -# [13:44:49][I][ble_client:341]: characteristic 0xFFE2, handle 0x7, properties 0x1c -# [13:44:49][I][ble_client:161]: Service UUID: 0x1800 -# [13:44:49][I][ble_client:162]: start_handle: 0xa end_handle: 0x14 -# [13:44:49][I][ble_client:341]: characteristic 0x2A00, handle 0xc, properties 0x2 -# [13:44:49][I][ble_client:341]: characteristic 0x2A01, handle 0xe, properties 0x2 -# [13:44:49][I][ble_client:341]: characteristic 0x2A02, handle 0x10, properties 0xa -# [13:44:49][I][ble_client:341]: characteristic 0x2A05, handle 0x17, properties 0x20 -ble_client: - - mac_address: "7C:01:0A:43:4E:9E" - id: ph_260bd - on_connect: - then: - - wait_until: # wait until characteristic is discovered - lambda: |- - esphome::ble_client::BLEClient* client = id(ph_260bd); - - auto service_uuid = 0xFFE0; // can't get it off `sensor` because it is protected - auto char_uuid = 0xFFE1; // can't get it off `sensor` because it is protected - - esphome::ble_client::BLECharacteristic* chr = client->get_characteristic(service_uuid, char_uuid); - - return chr != nullptr; - - lambda: |- - ESP_LOGD("ble_client_lambda", "Connected to PH-260BD"); - - //esphome::ble_client::BLESensor* sensor = id(ph_260bd_sensor); - esphome::ble_client::BLEClient* client = id(ph_260bd); - - auto service_uuid = 0xFFE0; // can't get it off `sensor` because it is protected - auto char_uuid = 0xFFE1; // can't get it off `sensor` because it is protected - - esphome::ble_client::BLECharacteristic* chr = client->get_characteristic(service_uuid, char_uuid); - - if (chr == nullptr) { - ESP_LOGW("ble_client", "[0xFFE1] Characteristic not found. State update can not be written."); - } else { - unsigned char newVal[8] = { - 0x00, 0x03, 0x00, 0x00, - 0x00, 0x14, 0x44, 0x14 - }; - int status = esp_ble_gattc_write_char( - client->gattc_if, - client->conn_id, - chr->handle, - sizeof(newVal), - newVal, - ESP_GATT_WRITE_TYPE_NO_RSP, - ESP_GATT_AUTH_REQ_NONE - ); - - if (status) { - ESP_LOGW("ble_client", "Error sending write value to BLE gattc server, status=%d", status); - } - } - - /* - decltype(v)::foo = 1; // debug type of v by mis-casting it and looking at compiler error - */ - - on_disconnect: - then: - - lambda: |- - ESP_LOGD("ble_client", "Disconnected from PH-260BD"); - -sensor: - - platform: template - name: "Tent Reservoir EC (µS)" - id: ec_us - unit_of_measurement: "µS/cm" - accuracy_decimals: 0 - state_class: measurement - icon: mdi:water-opacity - filters: - - filter_out: nan - - throttle: 30s - - - platform: template - name: "Tent Reservoir Temperature" - id: temp - unit_of_measurement: "°C" - accuracy_decimals: 1 - state_class: measurement - device_class: temperature - filters: - - filter_out: nan - - throttle: 30s - - - platform: template - name: "Tent Reservoir pH" - id: ph - unit_of_measurement: "pH" - accuracy_decimals: 2 - state_class: measurement - icon: mdi:ph - filters: - - filter_out: nan - - throttle: 30s - - - platform: ble_client - ble_client_id: ph_260bd - id: ph_260bd_sensor - internal: true - service_uuid: FFE0 - characteristic_uuid: FFE1 - notify: true - - # The PH-260BD puts bytes onto the characteristic value which needs to be treated as text: - # - # [1] pry(main)> ['372e35312070480d0a32312e372020e284830d0a'].pack('H*') - # => "7.51 pH\r\n21.7 \xE2\x84\x83\r\n" - # [2] pry(main)> puts ['372e35312070480d0a32312e372020e284830d0a'].pack('H*') - # 7.51 pH - # 21.7 ℃ - # - # It alternates between putting the EC/TDS value alone (as a string, with units) and the pH and - # temperature together. Perhaps it can't fit all three in a single buffer. - # - # All values follow: number(s)/dot, space(s), unit, carriage return, new line - # - # This lambda parses the string and publishes each value+unit to the appropriate template sensor on each newline. - lambda: |- - ESP_LOGD("ble_client.receive", "value received with %d bytes: [%.*s]", x.size(), x.size(), &x[0]); - - if (x.size() == 0) return NAN; - //decltype(parse_float)::foo= 1; - - std::string val_str = ""; - std::string val_unit = ""; - - // ESP_LOGD("ble_client.receive", "value received with %d bytes: [%.*s]", x.size(), x.size(), &x[0]); - - // https://git.faked.org/jan/ph-260bd/-/blob/master/src/main.cpp#L7 - static int factorMsToPpm = 700; - - for (int i = 0; i < x.size(); i++) { - auto c = x[i]; - switch(c) { - case '\x30': // "0" - case '\x31': // "1" - case '\x32': // "2" - case '\x33': // "3" - case '\x34': // "4" - case '\x35': // "5" - case '\x36': // "6" - case '\x37': // "7" - case '\x38': // "8" - case '\x39': // "9" - case '\x2E': // "." - val_str += c; - break; - case '\x20': // " " - break; // proceed until we hit units - case '\x0d': // '\r' - break; // ignore - case '\x0a': // '\n' - // FIXME: Don't publish temperature when ppt is set as it drops the first char - - if (auto val = parse_number(val_str)) { - if (val_unit == "pH") { - id(ph).publish_state(*val); - } else if (val_unit == "\xE2\x84\x83") { // ℃ char - id(temp).publish_state(*val); - } else if (val_unit == "uS") { // microsiemens - id(ec_us)->publish_state(*val); - } else if (val_unit == "mS") { // millisiemens - id(ec_us)->publish_state(*val * 1000); - } else if (val_unit == "ppm") { // TDS parts per million - id(ec_us)->publish_state(*val / factorMsToPpm * 1000); - } else if (val_unit == "ppt") { // TDS parts per thousand - id(ec_us)->publish_state(*val / factorMsToPpm * 1000 * 1000); - - } else { - ESP_LOGW("ble_client.receive", "value received with unknown unit: [%s]", val_unit.c_str()); - } - } else { - ESP_LOGW("ble_client.receive", "value could not be parsed as float: [%s]", val_str.c_str()); - } - - val_unit = ""; - val_str = ""; - break; - default: - val_unit += c; - } - } - - return 0.0; // this sensor isn't actually used diff --git a/esphome/common/ble-gateway.yaml b/esphome/common/ble-gateway.yaml index 2bdd99e..be5f64b 100644 --- a/esphome/common/ble-gateway.yaml +++ b/esphome/common/ble-gateway.yaml @@ -6,6 +6,8 @@ esp32_ble_tracker: scan_parameters: active: false +bluetooth_proxy: + ble_gateway: id: blegateway discovery: true diff --git a/esphome/common/ph_260bd.yaml b/esphome/common/ph_260bd.yaml new file mode 100644 index 0000000..76d27d5 --- /dev/null +++ b/esphome/common/ph_260bd.yaml @@ -0,0 +1,195 @@ +# JDY-08 +# https://amperkot.ru/static/3236/uploads/datasheets/JDY-08.pdf +# [13:44:48][I][ble_client:085]: Attempting BLE connection to 7c:01:0a:43:4e:9e +# [13:44:49][D][ble_client_lambda:035]: Connected to BLE device +# [13:44:49][I][ble_client:161]: Service UUID: 0xFFE0 +# [13:44:49][I][ble_client:162]: start_handle: 0x1 end_handle: 0x9 +# [13:44:49][I][ble_client:341]: characteristic 0xFFE1, handle 0x3, properties 0x1c +# [13:44:49][I][ble_client:341]: characteristic 0xFFE2, handle 0x7, properties 0x1c +# [13:44:49][I][ble_client:161]: Service UUID: 0x1800 +# [13:44:49][I][ble_client:162]: start_handle: 0xa end_handle: 0x14 +# [13:44:49][I][ble_client:341]: characteristic 0x2A00, handle 0xc, properties 0x2 +# [13:44:49][I][ble_client:341]: characteristic 0x2A01, handle 0xe, properties 0x2 +# [13:44:49][I][ble_client:341]: characteristic 0x2A02, handle 0x10, properties 0xa +# [13:44:49][I][ble_client:341]: characteristic 0x2A05, handle 0x17, properties 0x20 +ble_client: + - mac_address: "7C:01:0A:43:4E:9E" + id: ph_260bd + on_connect: + then: + - wait_until: # wait until characteristic is discovered + lambda: |- + esphome::ble_client::BLEClient* client = id(ph_260bd); + + auto service_uuid = 0xFFE0; // can't get it off `sensor` because it is protected + auto char_uuid = 0xFFE1; // can't get it off `sensor` because it is protected + + esphome::ble_client::BLECharacteristic* chr = client->get_characteristic(service_uuid, char_uuid); + + return chr != nullptr; + - lambda: |- + ESP_LOGD("ble_client_lambda", "Connected to PH-260BD"); + + //esphome::ble_client::BLESensor* sensor = id(ph_260bd_sensor); + esphome::ble_client::BLEClient* client = id(ph_260bd); + + auto service_uuid = 0xFFE0; // can't get it off `sensor` because it is protected + auto char_uuid = 0xFFE1; // can't get it off `sensor` because it is protected + + esphome::ble_client::BLECharacteristic* chr = client->get_characteristic(service_uuid, char_uuid); + + if (chr == nullptr) { + ESP_LOGW("ble_client", "[0xFFE1] Characteristic not found. State update can not be written."); + } else { + unsigned char newVal[8] = { + 0x00, 0x03, 0x00, 0x00, + 0x00, 0x14, 0x44, 0x14 + }; + int status = esp_ble_gattc_write_char( + client->gattc_if, + client->conn_id, + chr->handle, + sizeof(newVal), + newVal, + ESP_GATT_WRITE_TYPE_NO_RSP, + ESP_GATT_AUTH_REQ_NONE + ); + + if (status) { + ESP_LOGW("ble_client", "Error sending write value to BLE gattc server, status=%d", status); + } + } + + /* + decltype(v)::foo = 1; // debug type of v by mis-casting it and looking at compiler error + */ + + on_disconnect: + then: + - lambda: |- + ESP_LOGD("ble_client", "Disconnected from PH-260BD"); + +sensor: + - platform: template + name: "Tent Reservoir EC (µS)" + id: ec_us + unit_of_measurement: "µS/cm" + accuracy_decimals: 0 + state_class: measurement + icon: mdi:water-opacity + filters: + - filter_out: nan + - throttle: 30s + + - platform: template + name: "Tent Reservoir Temperature" + id: temp + unit_of_measurement: "°C" + accuracy_decimals: 1 + state_class: measurement + device_class: temperature + filters: + - filter_out: nan + - throttle: 30s + + - platform: template + name: "Tent Reservoir pH" + id: ph + unit_of_measurement: "pH" + accuracy_decimals: 2 + state_class: measurement + icon: mdi:ph + filters: + - filter_out: nan + - throttle: 30s + + - platform: ble_client + type: characteristic + ble_client_id: ph_260bd + id: ph_260bd_sensor + internal: true + service_uuid: FFE0 + characteristic_uuid: FFE1 + notify: true + + # The PH-260BD puts bytes onto the characteristic value which needs to be treated as text: + # + # [1] pry(main)> ['372e35312070480d0a32312e372020e284830d0a'].pack('H*') + # => "7.51 pH\r\n21.7 \xE2\x84\x83\r\n" + # [2] pry(main)> puts ['372e35312070480d0a32312e372020e284830d0a'].pack('H*') + # 7.51 pH + # 21.7 ℃ + # + # It alternates between putting the EC/TDS value alone (as a string, with units) and the pH and + # temperature together. Perhaps it can't fit all three in a single buffer. + # + # All values follow: number(s)/dot, space(s), unit, carriage return, new line + # + # This lambda parses the string and publishes each value+unit to the appropriate template sensor on each newline. + lambda: |- + ESP_LOGD("ble_client.receive", "value received with %d bytes: [%.*s]", x.size(), x.size(), &x[0]); + + if (x.size() == 0) return NAN; + //decltype(parse_float)::foo= 1; + + std::string val_str = ""; + std::string val_unit = ""; + + // ESP_LOGD("ble_client.receive", "value received with %d bytes: [%.*s]", x.size(), x.size(), &x[0]); + + // https://git.faked.org/jan/ph-260bd/-/blob/master/src/main.cpp#L7 + static int factorMsToPpm = 700; + + for (int i = 0; i < x.size(); i++) { + auto c = x[i]; + switch(c) { + case '\x30': // "0" + case '\x31': // "1" + case '\x32': // "2" + case '\x33': // "3" + case '\x34': // "4" + case '\x35': // "5" + case '\x36': // "6" + case '\x37': // "7" + case '\x38': // "8" + case '\x39': // "9" + case '\x2E': // "." + val_str += c; + break; + case '\x20': // " " + break; // proceed until we hit units + case '\x0d': // '\r' + break; // ignore + case '\x0a': // '\n' + // FIXME: Don't publish temperature when ppt is set as it drops the first char + + if (auto val = parse_number(val_str)) { + if (val_unit == "pH") { + id(ph).publish_state(*val); + } else if (val_unit == "\xE2\x84\x83") { // ℃ char + id(temp).publish_state(*val); + } else if (val_unit == "uS") { // microsiemens + id(ec_us)->publish_state(*val); + } else if (val_unit == "mS") { // millisiemens + id(ec_us)->publish_state(*val * 1000); + } else if (val_unit == "ppm") { // TDS parts per million + id(ec_us)->publish_state(*val / factorMsToPpm * 1000); + } else if (val_unit == "ppt") { // TDS parts per thousand + id(ec_us)->publish_state(*val / factorMsToPpm * 1000 * 1000); + + } else { + ESP_LOGW("ble_client.receive", "value received with unknown unit: [%s]", val_unit.c_str()); + } + } else { + ESP_LOGW("ble_client.receive", "value could not be parsed as float: [%s]", val_str.c_str()); + } + + val_unit = ""; + val_str = ""; + break; + default: + val_unit += c; + } + } + + return 0.0; // this sensor isn't actually used diff --git a/lovelace/lovelace.bos_office.yaml b/lovelace/lovelace.bos_office.yaml index 40310ff..8c4bb7d 100644 --- a/lovelace/lovelace.bos_office.yaml +++ b/lovelace/lovelace.bos_office.yaml @@ -59,6 +59,11 @@ config: - cards: - entities: - entity: automation.warm_up_bo_s_office + icon: mdi:heating-coil + name: Keep warm + - entity: input_number.bo_s_office_target_temperature + icon: mdi:temperature-celsius + name: Target type: entities - entities: - entity: sensor.ble_temperature_bos_office_a4c1380f0b98 diff --git a/lovelace/lovelace.lovelace_gardens.yaml b/lovelace/lovelace.lovelace_gardens.yaml index bbdba21..455f6db 100644 --- a/lovelace/lovelace.lovelace_gardens.yaml +++ b/lovelace/lovelace.lovelace_gardens.yaml @@ -10,9 +10,11 @@ config: - state: unavailable - area: Garden Shed - entity_id: /human_readable/ + - entity_id: /garden_shed/ include: - name: /[gG]arden/ - - name: /[tT]ent/ + options: + secondary_info: last-updated type: custom:auto-entities - card: type: history-graph @@ -24,12 +26,20 @@ config: - state: unavailable - area: Garden Shed - entity_id: /human_readable/ + - entity_id: /garden_shed/ include: - name: /[gG]arden/ - name: /[tT]ent/ - entity_id: sensor.home_weather_temperature - entity_id: sensor.home_weather_forecast_temperature type: custom:auto-entities + - entities: + - entity: sensor.ble_humidity_greenhouse_a4c1381cb175 + secondary_info: last-changed + - entity: sensor.ble_temperature_greenhouse_a4c1381cb175 + secondary_info: last-changed + title: Greenhouse (A4C1381CB175) + type: entities icon: mdi:flower path: garden title: Garden @@ -53,12 +63,6 @@ config: show_state: true - entity: switch.tent_cam_night_vision show_state: true - - entity: sensor.tent_cam_battery_level - show_state: true - - entity: sensor.tent_cam_battery_temperature - show_state: true - - entity: sensor.tent_cam_light_level - show_state: true type: picture-glance view_layout: position: sidebar @@ -107,7 +111,7 @@ config: state_color: true tap_action: action: toggle - entity: switch.tent_power_plug + entity: sensor.tent_wattage name: Power secondary_info: entity: sensor.tent_wattage @@ -127,29 +131,15 @@ config: position: sidebar - entities: - entities: - - entity: sensor.tent_humidity + - entity: sensor.ble_humidity_tent_a4c1385ec751 format: precision1 name: Humidity - entity: sensor.tent_temperature + entity: sensor.ble_temperature_tent_a4c1385ec751 format: precision1 icon: mdi:tent name: Tent state_header: Temperature type: custom:multiple-entity-row - - entities: - - entity: sensor.tent_reservoir_ec_us - format: kilo - name: EC - unit: false - - entity: sensor.tent_reservoir_ph - name: pH - unit: false - entity: sensor.tent_reservoir_temperature - format: precision1 - icon: mdi:cup-water - name: Reservoir - state_header: Temperature - type: custom:multiple-entity-row show_header_toggle: false state_color: false type: entities @@ -264,10 +254,10 @@ config: show_state: false type: custom:multiple-entity-row - entities: - - hide_if_template: '{% set v = states(''sensor.tent_humidity'') %} {% set - min = states(''input_number.minimum_tent_humidity'') %} {% set max = - states(''input_number.maximum_tent_humidity'') %} {{ iif(v < max and - v > min, v, -1 * v) }}' + - hide_if_template: '{% set v = states(''sensor.ble_humidity_tent_a4c1385ec751'') + %} {% set min = states(''input_number.minimum_tent_humidity'') %} {% + set max = states(''input_number.maximum_tent_humidity'') %} {{ iif(v + < max and v > min, v, -1 * v) }}' icon: mdi:alert-decagram styles: --paper-item-icon-color: red @@ -311,18 +301,18 @@ config: service: input_number.increment service_data: entity_id: input_number.maximum_tent_humidity - entity: sensor.tent_humidity + entity: sensor.ble_humidity_tent_a4c1385ec751 name: Humidity secondary_info: - entity: sensor.tent_humidity + entity: sensor.ble_humidity_tent_a4c1385ec751 name: false show_state: false type: custom:multiple-entity-row - entities: - - hide_if_template: '{% set v = states(''sensor.tent_temperature'') %} {% - set min = states(''input_number.minimum_tent_temperature'') %} {% set - max = states(''input_number.maximum_tent_temperature'') %} {{ iif(v - < max and v > min, v, -1 * v) }}' + - hide_if_template: '{% set v = states(''sensor.ble_temperature_tent_a4c1385ec751'') + %} {% set min = states(''input_number.minimum_tent_temperature'') %} + {% set max = states(''input_number.maximum_tent_temperature'') %} {{ + iif(v < max and v > min, v, -1 * v) }}' icon: mdi:alert-decagram styles: --paper-item-icon-color: red @@ -366,11 +356,11 @@ config: service: input_number.increment service_data: entity_id: input_number.maximum_tent_temperature - entity: sensor.tent_temperature + entity: sensor.ble_temperature_tent_a4c1385ec751 icon: mdi:temperature-celsius name: Temperature secondary_info: - entity: sensor.tent_temperature + entity: sensor.ble_temperature_tent_a4c1385ec751 name: false show_state: false type: custom:multiple-entity-row @@ -388,8 +378,8 @@ config: entities: - sensor.tent_reservoir_ph - sensor.tent_vpd - - sensor.tent_humidity - - sensor.tent_temperature + - sensor.ble_humidity_tent_a4c1385ec751 + - sensor.ble_temperature_tent_a4c1385ec751 - input_number.minimum_ph - input_number.maximum_ph - input_number.minimum_tent_vpd @@ -402,24 +392,43 @@ config: view_layout: position: sidebar - cards: - - days_to_show: 3 - entities: - - entity: sensor.bendigo_temp - - entity: sensor.home_weather_temperature - name: Weather - - entity: sensor.tent_temperature - name: Tent + - cards: + - entities: + - entity: sensor.home_weather_temperature + name: Weather + - entity: sensor.ble_temperature_tent_a4c1385ec751 + name: Tent + - attribute: current_temperature + entity: climate.garden_shed + icon: mdi:thermometer + name: Shed + suffix: "\xB0C" + type: attribute + type: entities + - days_to_show: 3 + entities: + - entity: sensor.home_weather_temperature + name: Weather + - entity: sensor.ble_temperature_tent_a4c1385ec751 + name: Tent + type: statistics-graph title: Air Temperatures - type: statistics-graph + type: custom:stack-in-card - days_to_show: 3 entities: - - entity: sensor.bendigo_humidity - entity: sensor.home_weather_humidity name: Weather - - entity: sensor.tent_humidity + - entity: sensor.ble_humidity_tent_a4c1385ec751 name: Tent title: Humidity type: statistics-graph + - air_rh: sensor.ble_humidity_tent_a4c1385ec751 + air_temp: sensor.ble_temperature_tent_a4c1385ec751 + crop: Cannabis + leaf_temp: sensor.ble_temperature_tent_a4c1385ec751 + leaf_temp_offset: -2 + title: Veg tent + type: custom:vpdchart-card - days_to_show: 3 entities: - entity: sensor.tent_vpd @@ -428,30 +437,9 @@ config: type: statistics-graph - days_to_show: 3 entities: - - entity: sensor.tent_reservoir_temperature - name: "\xB0C" - refresh_interval: 120 - title: Reservoir Temperature - type: statistics-graph - - days_to_show: 3 - entities: - - entity: sensor.tent_reservoir_ec_us - name: EC - refresh_interval: 120 - title: Reservoir EC - type: statistics-graph - - days_to_show: 3 - entities: - - entity: sensor.tent_reservoir_ph - name: pH - refresh_interval: 120 - title: Reservoir pH - type: statistics-graph - - days_to_show: 3 - entities: - - entity: sensor.tent_hhcc_1_illuminance + - entity: sensor.ble_illuminance_tent_c47c8d6dd13f name: A - - entity: sensor.tent_hhcc_2_illuminance + - entity: sensor.ble_illuminance_tent_c47c8d6dd155 name: B stat_types: - max @@ -459,25 +447,25 @@ config: type: statistics-graph - days_to_show: 3 entities: - - entity: sensor.tent_hhcc_1_moisture + - entity: sensor.ble_moisture_tent_c47c8d6dd13f name: A - - entity: sensor.tent_hhcc_2_moisture + - entity: sensor.ble_moisture_tent_c47c8d6dd155 name: B title: Soil Moisture type: statistics-graph - days_to_show: 3 entities: - - entity: sensor.tent_hhcc_1_temperature + - entity: sensor.ble_temperature_tent_c47c8d6dd13f name: A - - entity: sensor.tent_hhcc_2_temperature + - entity: sensor.ble_temperature_tent_c47c8d6dd155 name: B title: Soil Temperatures type: statistics-graph - days_to_show: 3 entities: - - entity: sensor.tent_hhcc_1_soil_conductivity + - entity: sensor.ble_conductivity_tent_c47c8d6dd13f name: A - - entity: sensor.tent_hhcc_2_soil_conductivity + - entity: sensor.ble_conductivity_tent_c47c8d6dd155 name: B title: Soil EC type: statistics-graph @@ -490,9 +478,7 @@ config: title: Automations type: entities filter: - exclude: - - name: /Snapshot|Restore/ - - entity_id: /night_mode/ + exclude: null include: - entity_id: script.refill_tent_humidifier options: @@ -525,7 +511,8 @@ config: - domain: script or: - entity_id: /tent/ - - area: Garden Shed + - area_id: /tent/ + - area: /Tent/ sort: entities: - hide_if: 'on' @@ -543,7 +530,6 @@ config: method: last_triggered reverse: true - domain: automation - entity_id: /tent/ options: entities: - icon: mdi:play @@ -556,6 +542,11 @@ config: state_color: true toggle: true type: custom:multiple-entity-row + or: + - entity_id: /tent/ + - entity_id: /grow_camera/ + - area_id: /tent/ + - area: /Tent/ sort: method: last_triggered reverse: true @@ -568,15 +559,11 @@ config: view_layout: position: sidebar - entities: - - entity: button.garden_shed_ble_relay_restart + - entity: button.garden_shed_ble_gateway_restart name: Restart - - entity: binary_sensor.garden_shed_ble_relay_status - name: Status secondary_info: last-changed - - entity: sensor.garden_shed_ble_relay_wifi_signal + - entity: sensor.garden_shed_ble_gateway_wifi_signal name: Wi-fi Signal - - entity: sensor.garden_shed_ble_relay_uptime_human_readable - name: Uptime title: Sensor Proxy type: entities view_layout: diff --git a/lovelace/lovelace.lovelace_servers.yaml b/lovelace/lovelace.lovelace_servers.yaml index d696adb..9473274 100644 --- a/lovelace/lovelace.lovelace_servers.yaml +++ b/lovelace/lovelace.lovelace_servers.yaml @@ -60,6 +60,28 @@ config: - entities: - entity: switch.nas - entity: switch.tumtum + - type: section + - entity: automation.power_nas_tumtum_according_to_sleep + name: Turn off while sleeping + type: entities + - entities: + - entity: sensor.ups_status + name: Status + - entity: sensor.ups_battery_charge + name: Charge + - entity: sensor.ups_load + name: Load + - entity: automation.notify_on_ups_state_change + name: Notify on state change + - entity: automation.power_nas_tumtum_according_to_ups + name: Shutdown servers on battery + footer: + detail: 2 + entity: sensor.ups_battery_charge + hours_to_show: 6 + type: graph + show_header_toggle: false + title: UPS type: entities icon: mdi:wardrobe-outline path: server-closet @@ -295,6 +317,54 @@ config: path: hass theme: Backend-selected title: HASS + - badges: [] + cards: + - entities: + - entity: device_tracker.ugw3 + - entity: sensor.unifi_gateway_alerts + - entity: device_tracker.unifi_controller + - entity: sensor.unifi_gateway_firmware_upgradable + - entity: sensor.unifi_gateway_lan + - entity: sensor.unifi_gateway_vpn + - entity: sensor.unifi_gateway_www + - entity: sensor.unifi_gateway_wlan + type: entities + - card: + type: entities + filter: + exclude: [] + include: + - integration: unifi + not: + domain: device_tracker + type: custom:auto-entities + - card: + state_color: true + title: Clients + type: entities + filter: + exclude: [] + include: + - domain: device_tracker + integration: unifi + options: + attribute: ip + type: attribute + sort: + method: friendly_name + state: home + - type: section + - domain: device_tracker + integration: unifi + not: + state: home + sort: + method: friendly_name + type: custom:auto-entities + icon: mdi:lan-connect + path: lan + theme: Backend-selected + title: LAN - badges: [] cards: - all_series_config: diff --git a/lovelace/lovelace.lovelace_solar.yaml b/lovelace/lovelace.lovelace_solar.yaml index 7534671..dfcf51b 100644 --- a/lovelace/lovelace.lovelace_solar.yaml +++ b/lovelace/lovelace.lovelace_solar.yaml @@ -87,7 +87,7 @@ config: name: peak entity: sensor.monthly_energy_import_offpeak format: precision1 - name: Cycle + name: Month state_header: offpeak type: custom:multiple-entity-row - entities: @@ -475,6 +475,8 @@ config: title: Settings type: entities - entities: + - entity: sensor.inverter_battery_mode + name: Current - action_name: Set entity: script.inverter_self_consumption icon: mdi:recycle-variant @@ -516,6 +518,10 @@ config: secondary_info: last-triggered toggle: true type: custom:multiple-entity-row + - entity: automation.inverter_maximise_output_new + icon: mdi:arrow-up-bold-box-outline + name: Maximise output (WIP) + secondary_info: last-triggered - entity: automation.update_pvoutput icon: mdi:solar-power-variant-outline name: Send to PVOutput @@ -534,6 +540,16 @@ config: - domain: script name: /[Ii]nverter/ type: custom:auto-entities + - card: + type: entities + filter: + include: + - entity_id: input_number.inverter_active_power_buffer + options: + name: Buffer + - attributes: + solar: 'true' + type: custom:auto-entities - cards: - entities: battery: sensor.inverter_battery_power @@ -545,9 +561,17 @@ config: w_decimals: 0 watt_threshold: 900 - entities: - - sensor.inverter_active_power + - entity: sensor.inverter_active_power + name: Active Power + - entity: sensor.inverter_battery_power + name: Battery Power type: entities type: custom:stack-in-card + - entities: + - entity: sensor.inverter_target_battery_level + - entity: sensor.inverter_battery_level + hours_to_show: 6 + type: history-graph icon: mdi:wrench path: configure theme: Backend-selected @@ -682,6 +706,19 @@ config: state_header: Current type: custom:multiple-entity-row type: entities + - entities: + - entity: sensor.inverter_pv_power + name: PV Power + - entity: sensor.inverter_mppt1_current + name: MPPT1 Current + - entity: sensor.inverter_mppt2_current + name: MPPT2 Current + - entity: sensor.inverter_mppt1_voltage + name: MPPT1 Voltage + - entity: sensor.inverter_mppt2_voltage + name: MPPT2 Voltage + hours_to_show: 2 + type: history-graph title: Panels type: custom:stack-in-card - entities: diff --git a/lovelace/lovelace.yaml b/lovelace/lovelace.yaml index 139dafc..83dd8da 100644 --- a/lovelace/lovelace.yaml +++ b/lovelace/lovelace.yaml @@ -3,26 +3,6 @@ config: views: - badges: [] cards: - - card: - type: custom:mushroom-chips-card - card_param: chips - filter: - exclude: - - entity_id: /tent/ - - entity_id: '*double_lamp_*' - - area: Garden Shed - - name: /Purifier/ - include: - - domain: light - options: - content_info: name - type: light - use_light_color: true - sort: - method: name - sort: - method: friendly_name - type: custom:auto-entities - cards: - card: chips: @@ -147,6 +127,7 @@ config: - state: standby - entity_id: /spotify/ - entity_id: /denon/ + - entity_id: /global/ - attributes: source: HEOS Music include: @@ -199,6 +180,7 @@ config: - state: unknown - entity_id: /vacuum.*attached/ - entity_id: /inverter_.*_soc/ + - entity_id: /athom/ include: - attributes: device_class: moisture @@ -286,78 +268,191 @@ config: type: custom:power-flow-card w_decimals: 0 watt_threshold: 900 - - elements: - - attribute: mean - entity: sensor.ble_temperature_living_room_a4c1382a9b6e - style: - background: rgba(10,10,10,0.2) - left: 23% - padding: 3px - top: 22% - suffix: "\xB0C" - tap_action: more-info - type: custom:state-attribute-element - - attribute: mean - entity: sensor.ble_temperature_bos_office_a4c1380f0b98 - style: - background: rgba(10,10,10,0.2) - left: 72% - padding: 3px - top: 80% - suffix: "\xB0C" - tap_action: more-info - type: custom:state-attribute-element - - attribute: mean - entity: sensor.ble_temperature_ris_office_a4c138e78afe - style: - background: rgba(10,10,10,0.2) - left: 88.8% - padding: 3px - top: 80% - suffix: "\xB0C" - tap_action: more-info - type: custom:state-attribute-element - - attribute: mean - entity: sensor.ble_temperature_analog_room_a4c138bcab08 - style: - background: rgba(10,10,10,0.2) - left: 80% - padding: 3px - top: 47% - suffix: "\xB0C" - type: custom:state-attribute-element - - attribute: mean - entity: sensor.ble_temperature_kitchen_a4c1389485e3 - style: - background: rgba(10,10,10,0.2) - left: 53.3% - padding: 3px - top: 20% - suffix: "\xB0C" - tap_action: more-info - type: custom:state-attribute-element - - attribute: mean - entity: sensor.ble_temperature_bedroom_a4c138feb60c - style: - background: rgba(10,10,10,0.2) - left: 29% - padding: 3px - top: 77% - suffix: "\xB0C" - tap_action: more-info - type: custom:state-attribute-element - - attribute: mean - entity: sensor.ble_temperature_spare_room_a4c138d8ef42 - style: - background: rgba(10,10,10,0.2) - left: 53.3% - padding: 3px - top: 80% - suffix: "\xB0C" - tap_action: more-info - type: custom:state-attribute-element - image: /local/floorplan-top.jpg - type: picture-elements + - cards: + - collapsible_controls: false + entity: climate.living_room_a_c + fill_container: true + hvac_modes: + - auto + - dry + - heat + - cool + - 'off' + - heat_cool + icon: mdi:air-conditioner + layout: horizontal + primary_info: state + secondary_info: last-changed + show_temperature_control: true + type: custom:mushroom-climate-card + - card: + entities: + - switch.living_room_a_c_ionizer + type: entities + conditions: + - entity: climate.living_room_a_c + state_not: 'off' + type: conditional + - card: + entities: + - switch.living_room_a_c_jet_mode + type: entities + conditions: + - entity: switch.living_room_a_c_jet_mode + state_not: unavailable + type: conditional + - entities: + - entity: climate.living_room_a_c + name: A/C + - entity: sensor.ble_temperature_living_room_a4c1382a9b6e + - entity: sensor.area_temperature_degc_living_room + name: Average temperature + hours_to_show: 6 + type: history-graph + type: custom:stack-in-card + icon: hass:home + panel: false + path: default_view + title: Home + - badges: [] + cards: + - cards: + - cards: + - entity: person.bo_jeanes + fill_container: false + hide_name: false + hide_state: false + type: custom:mushroom-person-card + use_entity_picture: true + - double_tap_action: + action: none + entity: sensor.template_room_bo_phone + icon: "{% if is_state(entity, 'not_home') and is_state('person.bo_jeanes',\ + \ 'home') %}\n mdi:cellphone-off\n{% else %}\n mdi:cellphone-marker\n\ + {% endif %}" + secondary: "{% if is_state('person.bo_jeanes', 'not_home') %}\n ~{{ states('proximity.bo_home')\ + \ }}m from home\n{% elif is_state(entity, 'not_home') %}\n Unknown\n\ + {% else %}\n {{ states(entity) | replace(\"_s_\",\"'s \") | replace(\"\ + _\",\" \") | title }}\n ~{{ state_attr(entity, 'distance') }}m\n{% endif\ + \ %}" + tap_action: + action: more-info + type: custom:mushroom-template-card + type: vertical-stack + - cards: + - entity: person.ri_liu + fill_container: false + hide_name: false + hide_state: false + layout: horizontal + type: custom:mushroom-person-card + use_entity_picture: true + - double_tap_action: + action: none + entity: sensor.template_room_ri_phone + icon: "{% if is_state(entity, 'not_home') and is_state('person.ri_liu',\ + \ 'home') %}\n mdi:cellphone-off\n{% else %}\n mdi:cellphone-marker\n\ + {% endif %}" + secondary: "{% if is_state('person.ri_liu', 'not_home') %}\n ~{{ states('proximity.ri_home')\ + \ }}m from home\n{% elif is_state(entity, 'not_home') %}\n Unknown\n\ + {% else %}\n {{ states(entity) | replace(\"_s_\",\"'s \") | replace(\"\ + _\",\" \") | title }}\n ~{{ state_attr(entity, 'distance') }}m\n{% endif\ + \ %}" + tap_action: + action: more-info + type: custom:mushroom-template-card + type: vertical-stack + type: horizontal-stack + - aspect_ratio: '16:9' + auto_fit: true + entities: + - entity: person.bo_jeanes + - entity: person.ri_liu + hours_to_show: 12 + type: map + icon: mdi:account-supervisor-circle + path: people + theme: Backend-selected + title: People + - badges: [] + cards: + - entities: + - entity: binary_sensor.in_bed + name: Anyone In bed + secondary_info: last-updated + - entity: input_boolean.bo_in_bed + - entity: input_boolean.ri_in_bed + - entity: cover.bedroom_blinds + - entity: sensor.bedroom_blinds_motor_state + - entity: automation.in_bed_detection + - entity: automation.manage_bedroom_blinds + type: entities + - chips: + - entity: binary_sensor.in_bed + type: entity + type: custom:mushroom-chips-card + - double_tap_action: + action: toggle + entity: cover.bedroom_blinds + fill_container: false + primary_info: name + show_buttons_control: false + show_position_control: true + type: custom:mushroom-cover-card + icon: mdi:bed + path: bedroom + theme: Backend-selected + title: Bedroom + - badges: [] + cards: + - entity: weather.home_weather + number_of_forecasts: '3' + type: custom:weather-card + - entities: + - entity: sun.sun + - entity: sensor.home_weather_condition + - entity: sensor.home_weather_temperature + name: "\xB0C Current" + - entity: sensor.home_weather_humidity + name: Humidity + - entity: sensor.home_weather_cloud_coverage + name: Cloud coverage + hours_to_show: 24 + refresh_interval: 0 + type: history-graph + - center_latitude: -36.7769283 + center_longitude: 144.2634146 + extra_labels: true + map_style: Voyager + marker_latitude: -36.7769283 + marker_longitude: 144.2634146 + show_marker: true + show_range: true + show_zoom: true + type: custom:bom-radar-card + zoom_level: 8 + - entities: + - entity: sun.sun + - entity: weather.home_weather + - entity: sensor.home_weather_condition + - entity: sensor.home_weather_forecast_condition + - entity: weather.home + - entity: weather.home_hourly + - entity: sensor.home_weather_cloud_coverage + - entity: sensor.home_weather_forecast_cloud_coverage + type: history-graph + icon: hass:thermometer + path: climate + title: Climate + - badges: [] + cards: + - calibration_source: + camera: true + entity: vacuum.robot_vacuum + map_source: + camera: camera.vacuum_map + type: custom:xiaomi-vacuum-map-card + vacuum_platform: default - calibration_source: camera: true entity: vacuum.dreame_p2028_4394_robot_cleaner @@ -502,166 +597,6 @@ config: two_finger_pan: true type: custom:xiaomi-vacuum-map-card vacuum_platform: default - icon: hass:home - panel: false - path: default_view - title: Home - - badges: [] - cards: - - cards: - - cards: - - entity: person.bo_jeanes - fill_container: false - hide_name: false - hide_state: false - type: custom:mushroom-person-card - use_entity_picture: true - - double_tap_action: - action: none - entity: sensor.template_room_bo_phone - icon: "{% if is_state(entity, 'not_home') and is_state('person.bo_jeanes',\ - \ 'home') %}\n mdi:cellphone-off\n{% else %}\n mdi:cellphone-marker\n\ - {% endif %}" - secondary: "{% if is_state('person.bo_jeanes', 'not_home') %}\n ~{{ states('proximity.bo_home')\ - \ }}m from home\n{% elif is_state(entity, 'not_home') %}\n Unknown\n\ - {% else %}\n {{ states(entity) | replace(\"_s_\",\"'s \") | replace(\"\ - _\",\" \") | title }}\n ~{{ state_attr(entity, 'distance') }}m\n{% endif\ - \ %}" - tap_action: - action: more-info - type: custom:mushroom-template-card - type: vertical-stack - - cards: - - entity: person.ri_liu - fill_container: false - hide_name: false - hide_state: false - layout: horizontal - type: custom:mushroom-person-card - use_entity_picture: true - - double_tap_action: - action: none - entity: sensor.template_room_ri_phone - icon: "{% if is_state(entity, 'not_home') and is_state('person.ri_liu',\ - \ 'home') %}\n mdi:cellphone-off\n{% else %}\n mdi:cellphone-marker\n\ - {% endif %}" - secondary: "{% if is_state('person.ri_liu', 'not_home') %}\n ~{{ states('proximity.ri_home')\ - \ }}m from home\n{% elif is_state(entity, 'not_home') %}\n Unknown\n\ - {% else %}\n {{ states(entity) | replace(\"_s_\",\"'s \") | replace(\"\ - _\",\" \") | title }}\n ~{{ state_attr(entity, 'distance') }}m\n{% endif\ - \ %}" - tap_action: - action: more-info - type: custom:mushroom-template-card - type: vertical-stack - type: horizontal-stack - icon: mdi:account-supervisor-circle - path: people - theme: Backend-selected - title: People - - badges: [] - cards: - - entities: - - entity: binary_sensor.in_bed - name: Anyone In bed - secondary_info: last-updated - - entity: input_boolean.bo_in_bed - - entity: input_boolean.ri_in_bed - type: entities - - aqi: - entity_id: sensor.bedroom_purifier_pm2_5 - unit: "\xB5g/m\xB3" - compact_view: true - entity: fan.bedroom_purifier - shortcuts: - - icon: mdi:weather-night - name: Silent - preset_mode: Silent - - icon: mdi:circle-slice-2 - name: 25% - percentage: 25 - - icon: mdi:circle-slice-4 - name: 50% - percentage: 50 - - icon: mdi:circle-slice-6 - name: 75% - percentage: 75 - - icon: mdi:circle-slice-8 - name: 100% - percentage: 100 - - icon: mdi:brightness-auto - name: Auto - preset_mode: Auto - show_name: false - show_state: false - show_toolbar: true - stats: - - entity_id: sensor.bedroom_purifier_temperature - unit: "\xB0C" - - entity_id: sensor.bedroom_purifier_humidity - unit: '%' - - entity_id: sensor.bedroom_purifier_filter_life_remaining - subtitle: Filter Remaining - unit: '%' - type: custom:purifier-card - - chips: - - entity: binary_sensor.in_bed - type: entity - type: custom:mushroom-chips-card - icon: mdi:bed - path: bedroom - theme: Backend-selected - title: Bedroom - - badges: [] - cards: - - entity: weather.home_weather - number_of_forecasts: '3' - type: custom:weather-card - - entities: - - entity: sun.sun - - entity: sensor.home_weather_condition - - entity: sensor.home_weather_temperature - name: "\xB0C Current" - - entity: sensor.home_weather_humidity - name: Humidity - - entity: sensor.home_weather_cloud_coverage - name: Cloud coverage - hours_to_show: 24 - refresh_interval: 0 - type: history-graph - - center_latitude: -36.7769283 - center_longitude: 144.2634146 - extra_labels: true - map_style: Voyager - marker_latitude: -36.7769283 - marker_longitude: 144.2634146 - show_marker: true - show_range: true - show_zoom: true - type: custom:bom-radar-card - zoom_level: 8 - - entities: - - entity: sun.sun - - entity: weather.home_weather - - entity: sensor.home_weather_condition - - entity: sensor.home_weather_forecast_condition - - entity: weather.home - - entity: weather.home_hourly - - entity: sensor.home_weather_cloud_coverage - - entity: sensor.home_weather_forecast_cloud_coverage - type: history-graph - icon: hass:thermometer - path: climate - title: Climate - - badges: [] - cards: - - calibration_source: - camera: true - entity: vacuum.robot_vacuum - map_source: - camera: camera.vacuum_map - type: custom:xiaomi-vacuum-map-card - vacuum_platform: default icon: '' panel: false path: misc diff --git a/lovelace/lovelace_resources.yaml b/lovelace/lovelace_resources.yaml index 0e56591..9e85024 100644 --- a/lovelace/lovelace_resources.yaml +++ b/lovelace/lovelace_resources.yaml @@ -4,7 +4,7 @@ items: url: /hacsfiles/mini-graph-card/mini-graph-card-bundle.js?hacstag=1512800620110 - id: 286fca3cd80f4192b815b715ef5f999e type: module - url: /hacsfiles/vertical-stack-in-card/vertical-stack-in-card.js?hacstag=142051833042 + url: /hacsfiles/vertical-stack-in-card/vertical-stack-in-card.js?hacstag=142051833044 - id: 032c18f548ea467b8bce3884fe451d82 type: module url: /hacsfiles/vacuum-card/vacuum-card.js?hacstag=261291295263 @@ -13,7 +13,7 @@ items: url: /hacsfiles/weather-card/weather-card.js - id: 69e31fab8ea64da890a5c68fc590320f type: module - url: /hacsfiles/lovelace-xiaomi-vacuum-map-card/xiaomi-vacuum-map-card.js?hacstag=1933720442011 + url: /hacsfiles/lovelace-xiaomi-vacuum-map-card/xiaomi-vacuum-map-card.js?hacstag=193372044212 - id: f2b643a296014c8292cbb3ba1b9af69b type: module url: /hacsfiles/kb-better-graph-colors/kb-better-graph-colors.js @@ -22,10 +22,10 @@ items: url: /hacsfiles/purifier-card/purifier-card.js?hacstag=274738925223 - id: c623d3fc8954431685d17cd75bf572bb type: module - url: /hacsfiles/apexcharts-card/apexcharts-card.js?hacstag=331701152201 + url: /hacsfiles/apexcharts-card/apexcharts-card.js?hacstag=331701152202 - id: 4cb20baf31e442e9830e4af74f089a0d type: module - url: /hacsfiles/lovelace-auto-entities/auto-entities.js?hacstag=1677445841110 + url: /hacsfiles/lovelace-auto-entities/auto-entities.js?hacstag=1677445841121 - id: 8468c5604c2d41d294fb0143cea43765 type: module url: /hacsfiles/simple-thermostat/simple-thermostat.js?hacstag=158654878243 @@ -49,7 +49,7 @@ items: url: /hacsfiles/miflora-card/miflora-card.js?hacstag=197715418010 - id: ddb6d1b21fc44ae692519ea38c9cf9cb type: module - url: /hacsfiles/bom-radar-card/bom-radar-card.js?hacstag=294609880206 + url: /hacsfiles/bom-radar-card/bom-radar-card.js?hacstag=294609880210 - id: edc63027be67460bab526d3dd3b4a8b2 type: module url: /hacsfiles/secondaryinfo-entity-row/secondaryinfo-entity-row.js?hacstag=15971160550 @@ -91,7 +91,7 @@ items: url: /hacsfiles/lovelace-paper-buttons-row/paper-buttons-row.js?hacstag=244872232101 - id: 78939a4781bd40f6accb3cba860a100f type: module - url: /hacsfiles/lovelace-mushroom/mushroom.js?hacstag=444350375200 + url: /hacsfiles/lovelace-mushroom/mushroom.js?hacstag=444350375213 - id: 4795f91c6d3a4fd3a5b1900f9990217e type: module url: /hacsfiles/stack-in-card/stack-in-card.js?hacstag=248954055020 @@ -109,7 +109,7 @@ items: url: /hacsfiles/lovelace-battery-entity-row/battery-entity-row.js?hacstag=303857065131 - id: 867c82efa08d47a3a9ccbe9f5afb238a type: module - url: /hacsfiles/numberbox-card/numberbox-card.js?hacstag=304967918312 + url: /hacsfiles/numberbox-card/numberbox-card.js?hacstag=30496791840 - id: 6a72c3dfa03446ffae4b9d8093bb5b7a type: module url: /hacsfiles/custom-ui/custom-ui.js?hacstag=267558148202204191 @@ -119,15 +119,6 @@ items: - id: 8217392f44e24fe98b652c7f36ab302e type: module url: /hacsfiles/ha-sankey-chart/ha-sankey-chart.js?hacstag=4558460880110 -- id: 84ed6341c9b245aba7e66cbdc51e2ccb - type: module - url: /hacsfiles/state-attribute-element/state-attribute-element.js?hacstag=142038085040 -- id: a70f15c06c9544b7bf7ad3bcf9dc6325 - type: module - url: /hacsfiles/state-element/state-element.js?hacstag=142344403002 -- id: ecebe38b38124fb1ba83b3ca1ee43e7d - type: module - url: /hacsfiles/text-element/text-element.js?hacstag=141897999002 - id: 0afffa6b08dd44be820b7e45428e0e4c type: module url: /hacsfiles/radial-menu/radial-menu.js?hacstag=181124811160 @@ -140,3 +131,6 @@ items: - id: c6b759faf93a4e22ab9faa3ebcaa218b type: module url: /hacsfiles/button-card/button-card.js?hacstag=146194325342 +- id: 9675930fcc78426396cc7c66b614f74c + type: module + url: /hacsfiles/vpdchart-card/vpdchart-card.js?hacstag=540873855100