diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml deleted file mode 100644 index 13f5280e..00000000 --- a/.github/workflows/build.yaml +++ /dev/null @@ -1,26 +0,0 @@ ---- -## Source: https://github.com/frenck/home-assistant-config/tree/master/.github/workflows -name: build -# yamllint disable-line rule:truthy -on: - push: - pull_request: - schedule: - - cron: 0 12 * * 4 -jobs: - home_assistant: - name: "Home Assistant Core ${{ matrix.version }} Configuration Check" - runs-on: ubuntu-latest - strategy: - matrix: - # ["stable", "beta", "dev"] - version: ["stable", "beta"] - steps: - - name: โคต๏ธ Check out configuration from GitHub - uses: actions/checkout@v4 - - name: ๐Ÿš€ Run Home Assistant Configuration Check - uses: frenck/action-home-assistant@v1.4 - with: - path: "." - secrets: ./.stubs/secrets.yaml - version: "${{ matrix.version }}" diff --git a/.github/workflows/home-assistant.yaml b/.github/workflows/home-assistant.yaml new file mode 100644 index 00000000..d1069452 --- /dev/null +++ b/.github/workflows/home-assistant.yaml @@ -0,0 +1,113 @@ +--- +# Source: https://github.com/frenck/action-home-assistant +# Example: https://github.com/frenck/home-assistant-config/blob/master/.github/workflows/home-assistant.yml +# +name: Home Assistant CI +# yamllint disable-line rule:truthy +on: + push: + pull_request: + schedule: + - cron: 0 12 * * 4 +jobs: + yamllint: + name: ๐Ÿงน YAML Lint + runs-on: ubuntu-latest + steps: + - name: ๐Ÿ“ฅ Check out repository + uses: actions/checkout@v4.1.1 + - name: ๐Ÿš€ Run YAMLlint + uses: frenck/action-yamllint@v1.4.1 + + remarklint: + name: ๐Ÿงน Remark Lint + runs-on: ubuntu-latest + steps: + - name: ๐Ÿ“ฅ Check out repository + uses: actions/checkout@v4.1.1 + - name: ๐Ÿš€ Run Remark lint + uses: "docker://pipelinecomponents/remark-lint:latest" + continue-on-error: true + with: + args: "remark --no-stdout --color --frail --use preset-lint-recommended ." + + ha_version: + name: "๐Ÿ  Get HA Version" + runs-on: ubuntu-latest + outputs: + current_version: ${{ steps.currentver.outputs.current_version }} + steps: + - name: ๐Ÿ“ฅ Check out repository + uses: actions/checkout@v4.1.1 + - name: ๐Ÿš€ Get Installed Version from .HA_VERSION + id: currentver + run: | + HA_VERSION=$(<.HA_VERSION) + echo $HA_VERSION + echo "current_version=$HA_VERSION" >> $GITHUB_OUTPUT + + home-assistant: + name: "๐Ÿ  HA Core ${{ matrix.version }} Check" + needs: [yamllint, ha_version] + runs-on: ubuntu-latest + strategy: + matrix: + version: ["${{ needs.ha_version.outputs.current_version }}", "stable", "beta", "dev"] + steps: + - name: ๐Ÿ“ฅ Check out repository + uses: actions/checkout@v4.1.1 + + - name: ๐Ÿ“„ Create empty files + run: | + touch ./home-assistant_v2.db + touch ./home-assistant.log + + - name: ๐Ÿ“ Create custom_components folder + run: | + mkdir -p ./custom_components + + # Check out custom components that require YAML configuration. + # yamllint disable rule:line-length + + - name: ๐Ÿ“ฅ Clone custom component (Dreamscreen) + run: | + git clone https://github.com/J3n50m4t/Home-Assistant-DreamScreen-Service.git + mv -v Home-Assistant-DreamScreen-Service/custom_components/* ./custom_components + + - name: ๐Ÿ“ฅ Clone custom component (UniFi Status) + run: | + git clone https://github.com/zvldz/unifi_status.git + mv -v unifi_status/custom_components/* ./custom_components + + # yamllint enable rule:line-length + + - name: ๐Ÿš€ Run Home Assistant Configuration Check + uses: frenck/action-home-assistant@v1.4 + with: + path: "." + secrets: ./.stubs/secrets.yaml + version: "${{ matrix.version }}" + + esphome: + name: "๐Ÿ› ๏ธ ESPHome Check" + runs-on: ubuntu-latest + needs: [yamllint] + steps: + - name: ๐Ÿ“ฅ Check out repository + uses: actions/checkout@v4.1.1 + - name: Set up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: "3.10" + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools wheel + pip install esphome + pip list + esphome version + - name: Copy secrets stub into configuration folder + run: cp ./.stubs/espsecrets.yaml ./esphome/secrets.yaml + - name: ๐Ÿš€ Run ESPHome on all files + # yamllint disable rule:line-length + run: | + for file in $(find ./esphome -type f -name "*.yaml" -maxdepth 1 -not -name "secrets.yaml"); do esphome config "${file}"; done diff --git a/.github/workflows/linters.yaml b/.github/workflows/linters.yaml deleted file mode 100644 index 5f15c84b..00000000 --- a/.github/workflows/linters.yaml +++ /dev/null @@ -1,25 +0,0 @@ ---- -## Source: https://github.com/frenck/home-assistant-config/tree/master/.github/workflows -name: linters -# yamllint disable-line rule:truthy -on: - - push -jobs: - yamllint: - runs-on: ubuntu-latest - steps: - - name: โคต๏ธ Check out configuration from GitHub - uses: actions/checkout@v4 - - name: ๐Ÿš€ Run YAMLlint - uses: frenck/action-yamllint@v1.4 - - remarklint: - runs-on: ubuntu-latest - steps: - - name: โคต๏ธ Check out configuration from GitHub - uses: actions/checkout@v4 - - name: ๐Ÿš€ Run Remark lint - uses: "docker://pipelinecomponents/remark-lint:latest" - continue-on-error: true - with: - args: "remark --no-stdout --color --frail --use preset-lint-recommended ." diff --git a/.stubs/espsecrets.yaml b/.stubs/espsecrets.yaml new file mode 100755 index 00000000..e106ebfc --- /dev/null +++ b/.stubs/espsecrets.yaml @@ -0,0 +1,9 @@ +--- +# Example Secrets +# +wifi_ssid: "wifi_ssid" +wifi_password: "wifi_password" +ota_password: "ota_password" +ap_password: "ap_password" +# Not my real key, nice try! +encryption_key: "QTuVWVmiUMboASbE3m5cpAN2wEKp80WfESFjmsNTlaM=" diff --git a/.yamllint b/.yamllint index 660261a8..5696fce7 100644 --- a/.yamllint +++ b/.yamllint @@ -3,9 +3,9 @@ ignore: | .history/ blueprints/ custom_components/ - integrations/keymaster/ - lovelace/minimalist.yaml + packages/keymaster/ themes/ + zigbee2mqtt/ automations.yaml customize.yaml govee_learning.yaml diff --git a/esphome/.gitignore b/esphome/.gitignore new file mode 100755 index 00000000..09af913d --- /dev/null +++ b/esphome/.gitignore @@ -0,0 +1,6 @@ +# Gitignore settings for ESPHome +# This is an example and may include too much for your use-case. +# You can modify this file to suit your needs. +/.esphome/ +/secrets.yaml +/trash/ diff --git a/esphome/car-presence.yaml b/esphome/car-presence.yaml new file mode 100755 index 00000000..047c9a4d --- /dev/null +++ b/esphome/car-presence.yaml @@ -0,0 +1,97 @@ +--- +# Car presence & position detection in Home Assistant with ESPHome +# source: https://adonno.com/car-presence-position-detection/ + +esphome: + name: car-presence + friendly_name: Car Presence + +esp8266: + board: d1_mini + +# Enable logging +logger: + +# Enable Home Assistant API +api: + encryption: + key: !secret encryption_key + +ota: + password: !secret ota_password + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + fast_connect: true + + # Enable fallback hotspot (captive portal) in case wifi connection fails + ap: + ssid: "AP" + password: !secret ap_password + ap_timeout: 3min + +captive_portal: + +time: + - platform: homeassistant + id: homeassistant_time + timezone: America/Boise + +text_sensor: + - platform: version + name: "ESPHome Version" + + - platform: wifi_info + ip_address: + name: "IP" + ssid: + name: "SSID" + bssid: + name: "BSSID" + +button: + - platform: restart + name: "Restart" + +binary_sensor: + - platform: template + name: "Left" + device_class: presence + lambda: |- + return id(car_presence_left_distance).state < 1.5; + + - platform: template + name: "Right" + device_class: presence + lambda: |- + return id(car_presence_right_distance).state < 1.5; + +sensor: + - platform: uptime + name: "Uptime" + unit_of_measurement: h + filters: + - lambda: return int((x + 1800.0) / 3600.0); + + - platform: wifi_signal + name: "Wifi Signal" + update_interval: 5min + + - platform: ultrasonic + name: "Left Distance" + id: "car_presence_left_distance" + trigger_pin: D1 + echo_pin: D2 + update_interval: 10s + filters: + - filter_out: nan + + - platform: ultrasonic + name: "Right Distance" + id: "car_presence_right_distance" + trigger_pin: D3 + echo_pin: D0 + update_interval: 10s + filters: + - filter_out: nan diff --git a/esphome/emporiavue.yaml b/esphome/emporiavue.yaml new file mode 100755 index 00000000..971ab47f --- /dev/null +++ b/esphome/emporiavue.yaml @@ -0,0 +1,371 @@ +--- +# Custom component for ESPHome to add support for the Emporia Vue 2 energy monitor +# Source: https://github.com/emporia-vue-local/esphome +# +# yamllint disable rule:brackets +# yamllint disable rule:colons + +esphome: + name: emporiavue + friendly_name: EmporiaVue + +substitutions: + timezone_name: "America/Boise" + + # Phases + phase_a_name: "Phase A" + phase_b_name: "Phase B" + + # Calibration + # To calculate new calibration value use the formula * / + # 0.022 is used as the default as starting point but may need adjusted to ensure accuracy + phase_a_calibration: "0.0231" + phase_b_calibration: "0.0217" + + # Suffixes + # Add a beginning space if you want a space between the circuit name and suffix. + power_suffix_name: " power" + current_suffix_name: " current" + daily_suffix_name: " daily" + voltage_suffix_name: " voltage" + frequency_suffix_name: " frequency" + phase_angle_suffix_name: " phase angle" + + # Calculated + total_name: "Total" + balance_name: "Balance" + + # Individual circuits + circuit_name_1: "Family room" + circuit_name_2: "Dishwasher, Disposal" + circuit_name_3: "Fridge, Kitchen outlets" + circuit_name_4: "Theater room" + circuit_name_5: "Washer" + circuit_name_6: "Basement bedrooms" + circuit_name_7: "Living room, Master bedroom" + circuit_name_8: "Bedrooms" + circuit_name_9: "Range" + circuit_name_10: "Dryer" + circuit_name_11: "Garage outlets" + circuit_name_12: "Utility room" + circuit_name_13: "Entry, Living room, Bath lights" + circuit_name_14: "Air conditioner" + circuit_name_15: "Microwave" + circuit_name_16: "Furnace" + + # Pay close attention to set the phase_id for each breaker by matching it to the phase/leg it connects to in the panel + circuit_phase_1: phase_a + circuit_phase_2: phase_b + circuit_phase_3: phase_a + circuit_phase_4: phase_b + circuit_phase_5: phase_b + circuit_phase_6: phase_a + circuit_phase_7: phase_b + circuit_phase_8: phase_a + circuit_phase_9: phase_a + circuit_phase_10: phase_a + circuit_phase_11: phase_a + circuit_phase_12: phase_b + circuit_phase_13: phase_a + circuit_phase_14: phase_b + circuit_phase_15: phase_b + circuit_phase_16: phase_a + + circuit_factor_1: "1" + circuit_factor_2: "1" + circuit_factor_3: "1" + circuit_factor_4: "1" + circuit_factor_5: "1" + circuit_factor_6: "1" + circuit_factor_7: "1" + circuit_factor_8: "1" + circuit_factor_9: "2" + circuit_factor_10: "2" + circuit_factor_11: "1" + circuit_factor_12: "1" + circuit_factor_13: "1" + circuit_factor_14: "2" + circuit_factor_15: "1" + circuit_factor_16: "1" + +external_components: + - source: github://emporia-vue-local/esphome@dev + components: + - emporia_vue + +esp32: + board: esp32dev + framework: + type: esp-idf + version: recommended + +# Enable Home Assistant API +api: + encryption: + key: !secret encryption_key + + services: + - service: play_rtttl + variables: + sound_str: string + then: + - rtttl.play: + rtttl: !lambda 'return sound_str;' + +# Enable OTA updates +ota: + password: !secret ota_password + +# Enable logging +logger: + logs: + # By default, every reading will be printed to the UART, which is very slow + # This will disable printing the readings but keep other helpful messages + sensor: INFO + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + fast_connect: true + +preferences: + # The default of 1min is far too short--flash chip is rated for approx 100k writes. + flash_write_interval: "48h" + +output: + - platform: ledc + pin: GPIO12 + id: buzzer + - platform: gpio + pin: GPIO27 + id: buzzer_gnd + +rtttl: + output: buzzer + on_finished_playback: + - logger.log: 'Sound ended!' + +button: + - platform: template + name: "Beep" + on_press: + - rtttl.play: "two short:d=4,o=5,b=100:16e6,16e6" + + - platform: restart + name: "Restart" + + - platform: factory_reset + name: "Factory Reset" + +light: + - platform: status_led + name: "LED" + pin: 23 + restore_mode: ALWAYS_ON + entity_category: config + +text_sensor: + - platform: version + name: "ESPHome Version" + + - platform: debug + reset_reason: + name: "Reset Reason" + +i2c: + sda: 21 + scl: 22 + scan: false + frequency: 200kHz # recommended range is 50-200kHz + id: i2c_a + +time: + - platform: homeassistant + id: homeassistant_time + timezone: $timezone_name + +debug: + update_interval: 120s + +# these are called references in YAML. They allow you to reuse +# this configuration in each sensor, while only defining it once +.defaultfilters: + - &throttle_avg + # average all raw readings together over a 5 second span before publishing + throttle_average: 5s + - &throttle_time + # only send the most recent measurement every 60 seconds + throttle: 60s + - &invert + # invert and filter out any values below 0. + lambda: 'return max(-x, 0.0f);' + - &pos + # filter out any values below 0. + lambda: 'return max(x, 0.0f);' + - &abs + # take the absolute value of the value + lambda: 'return abs(x);' + +sensor: + - platform: emporia_vue + i2c_id: i2c_a + phases: + - id: phase_a + input: BLACK + calibration: $phase_a_calibration + voltage: + name: "${phase_a_name}${voltage_suffix_name}" + filters: [ *throttle_avg, *pos ] + frequency: + name: "${phase_a_name}${frequency_suffix_name}" + filters: [ *throttle_avg, *pos ] + + - id: phase_b + input: RED + calibration: $phase_b_calibration + voltage: + name: "${phase_b_name}${voltage_suffix_name}" + filters: [ *throttle_avg, *pos ] + phase_angle: + name: "${phase_b_name}${phase_angle_suffix_name}" + filters: [ *throttle_avg, *pos ] + + ct_clamps: + # Do not specify a name for any of the power sensors here, only an id. This leaves the power sensors internal to ESPHome. + # Copy sensors will filter and then send power measurements to HA + # These non-throttled power sensors are used for accurately calculating energy + - phase_id: phase_a + input: "A" + power: + id: phase_a_power + filters: [ *pos ] + current: + id: phase_a_current + filters: [ *pos ] + + - phase_id: phase_b + input: "B" + power: + id: phase_b_power + filters: [ *pos ] + current: + id: phase_b_current + filters: [ *pos ] + + # Pay close attention to set the phase_id for each breaker by matching it to the phase/leg it connects to in the panel + - { phase_id: $circuit_phase_1, input: "1", power: { id: circuit_1_power, filters: [ *pos, multiply: $circuit_factor_1 ] } } + - { phase_id: $circuit_phase_2, input: "2", power: { id: circuit_2_power, filters: [ *pos, multiply: $circuit_factor_2 ] } } + - { phase_id: $circuit_phase_3, input: "3", power: { id: circuit_3_power, filters: [ *pos, multiply: $circuit_factor_3 ] } } + - { phase_id: $circuit_phase_4, input: "4", power: { id: circuit_4_power, filters: [ *pos, multiply: $circuit_factor_4 ] } } + - { phase_id: $circuit_phase_5, input: "5", power: { id: circuit_5_power, filters: [ *pos, multiply: $circuit_factor_5 ] } } + - { phase_id: $circuit_phase_6, input: "6", power: { id: circuit_6_power, filters: [ *pos, multiply: $circuit_factor_6 ] } } + - { phase_id: $circuit_phase_7, input: "7", power: { id: circuit_7_power, filters: [ *pos, multiply: $circuit_factor_7 ] } } + - { phase_id: $circuit_phase_8, input: "8", power: { id: circuit_8_power, filters: [ *pos, multiply: $circuit_factor_8 ] } } + - { phase_id: $circuit_phase_9, input: "9", power: { id: circuit_9_power, filters: [ *pos, multiply: $circuit_factor_9 ] } } + - { phase_id: $circuit_phase_10, input: "10", power: { id: circuit_10_power, filters: [ *pos, multiply: $circuit_factor_10 ] } } + - { phase_id: $circuit_phase_11, input: "11", power: { id: circuit_11_power, filters: [ *pos, multiply: $circuit_factor_11 ] } } + - { phase_id: $circuit_phase_12, input: "12", power: { id: circuit_12_power, filters: [ *pos, multiply: $circuit_factor_12 ] } } + - { phase_id: $circuit_phase_13, input: "13", power: { id: circuit_13_power, filters: [ *pos, multiply: $circuit_factor_13 ] } } + - { phase_id: $circuit_phase_14, input: "14", power: { id: circuit_14_power, filters: [ *pos, multiply: $circuit_factor_14 ] } } + - { phase_id: $circuit_phase_15, input: "15", power: { id: circuit_15_power, filters: [ *pos, multiply: $circuit_factor_15 ] } } + - { phase_id: $circuit_phase_16, input: "16", power: { id: circuit_16_power, filters: [ *pos, multiply: $circuit_factor_16 ] } } + on_update: + then: + - component.update: total_power + - component.update: balance_power + + # The copy sensors filter and send the power state to HA + - { platform: copy, source_id: phase_a_power, filters: *throttle_avg, name: "${phase_a_name}${power_suffix_name}" } + - { platform: copy, source_id: phase_b_power, filters: *throttle_avg, name: "${phase_b_name}${power_suffix_name}" } + + - { platform: copy, source_id: total_power, filters: *throttle_avg, name: "${total_name}${power_suffix_name}" } + - { platform: copy, source_id: balance_power, filters: *throttle_avg, name: "${balance_name}${power_suffix_name}" } + + - { platform: copy, source_id: phase_a_current, filters: *throttle_avg, name: "${phase_a_name}${current_suffix_name}" } + - { platform: copy, source_id: phase_b_current, filters: *throttle_avg, name: "${phase_b_name}${current_suffix_name}" } + + - { platform: copy, source_id: circuit_1_power, filters: *throttle_avg, name: "${circuit_name_1}${power_suffix_name}" } + - { platform: copy, source_id: circuit_2_power, filters: *throttle_avg, name: "${circuit_name_2}${power_suffix_name}" } + - { platform: copy, source_id: circuit_3_power, filters: *throttle_avg, name: "${circuit_name_3}${power_suffix_name}" } + - { platform: copy, source_id: circuit_4_power, filters: *throttle_avg, name: "${circuit_name_4}${power_suffix_name}" } + - { platform: copy, source_id: circuit_5_power, filters: *throttle_avg, name: "${circuit_name_5}${power_suffix_name}" } + - { platform: copy, source_id: circuit_6_power, filters: *throttle_avg, name: "${circuit_name_6}${power_suffix_name}" } + - { platform: copy, source_id: circuit_7_power, filters: *throttle_avg, name: "${circuit_name_7}${power_suffix_name}" } + - { platform: copy, source_id: circuit_8_power, filters: *throttle_avg, name: "${circuit_name_8}${power_suffix_name}" } + - { platform: copy, source_id: circuit_9_power, filters: *throttle_avg, name: "${circuit_name_9}${power_suffix_name}" } + - { platform: copy, source_id: circuit_10_power, filters: *throttle_avg, name: "${circuit_name_10}${power_suffix_name}" } + - { platform: copy, source_id: circuit_11_power, filters: *throttle_avg, name: "${circuit_name_11}${power_suffix_name}" } + - { platform: copy, source_id: circuit_12_power, filters: *throttle_avg, name: "${circuit_name_12}${power_suffix_name}" } + - { platform: copy, source_id: circuit_13_power, filters: *throttle_avg, name: "${circuit_name_13}${power_suffix_name}" } + - { platform: copy, source_id: circuit_14_power, filters: *throttle_avg, name: "${circuit_name_14}${power_suffix_name}" } + - { platform: copy, source_id: circuit_15_power, filters: *throttle_avg, name: "${circuit_name_15}${power_suffix_name}" } + - { platform: copy, source_id: circuit_16_power, filters: *throttle_avg, name: "${circuit_name_16}${power_suffix_name}" } + + # Mains Total Power + - platform: template + lambda: return id(phase_a_power).state + id(phase_b_power).state; + update_interval: never + id: total_power + device_class: power + state_class: measurement + unit_of_measurement: "W" + + # Mains Total Daily + - platform: total_daily_energy + name: "${total_name}${daily_suffix_name}" + power_id: total_power + accuracy_decimals: 2 + filters: [ *throttle_time, multiply: 0.001 ] + unit_of_measurement: "kWh" + + # Home Balance + - platform: template + lambda: !lambda |- + return max(0.0f, id(total_power).state - + id( circuit_1_power).state - + id( circuit_2_power).state - + id( circuit_3_power).state - + id( circuit_4_power).state - + id( circuit_5_power).state - + id( circuit_6_power).state - + id( circuit_7_power).state - + id( circuit_8_power).state - + id( circuit_9_power).state - + id(circuit_10_power).state - + id(circuit_11_power).state - + id(circuit_12_power).state - + id(circuit_13_power).state - + id(circuit_14_power).state - + id(circuit_15_power).state - + id(circuit_16_power).state); + update_interval: never + id: balance_power + device_class: power + state_class: measurement + unit_of_measurement: "W" + + # Home Balance Daily + - platform: total_daily_energy + name: "${balance_name}${daily_suffix_name}" + power_id: balance_power + accuracy_decimals: 2 + filters: [ *throttle_time, multiply: 0.001 ] + unit_of_measurement: "kWh" + + # Circuit Daily Energy + - { power_id: "circuit_1_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_1}${daily_suffix_name}" } + - { power_id: "circuit_2_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_2}${daily_suffix_name}" } + - { power_id: "circuit_3_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_3}${daily_suffix_name}" } + - { power_id: "circuit_4_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_4}${daily_suffix_name}" } + - { power_id: "circuit_5_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_5}${daily_suffix_name}" } + - { power_id: "circuit_6_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_6}${daily_suffix_name}" } + - { power_id: "circuit_7_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_7}${daily_suffix_name}" } + - { power_id: "circuit_8_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_8}${daily_suffix_name}" } + - { power_id: "circuit_9_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_9}${daily_suffix_name}" } + - { power_id: "circuit_10_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_10}${daily_suffix_name}" } + - { power_id: "circuit_11_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_11}${daily_suffix_name}" } + - { power_id: "circuit_12_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_12}${daily_suffix_name}" } + - { power_id: "circuit_13_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_13}${daily_suffix_name}" } + - { power_id: "circuit_14_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_14}${daily_suffix_name}" } + - { power_id: "circuit_15_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_15}${daily_suffix_name}" } + - { power_id: "circuit_16_power", platform: total_daily_energy, accuracy_decimals: 2, unit_of_measurement: "kWh", filters: [ *throttle_time, multiply: 0.001], name: "${circuit_name_16}${daily_suffix_name}" } diff --git a/esphome/water-softener-salt-monitor.yaml b/esphome/water-softener-salt-monitor.yaml new file mode 100755 index 00000000..ccb1eeba --- /dev/null +++ b/esphome/water-softener-salt-monitor.yaml @@ -0,0 +1,110 @@ +--- +# Water Softener Salt Level Monitor +# Monitors the salt level in a water softener using a sonic distance finder. +# +# Source: https://adonno.com/salt-level-sensor/ +# Source: https://www.chindemax.com/2020/10/14/walter-softener-salt-level-checker-uisng-nodemcu-homeassistant/ + +esphome: + name: water-softener-salt-monitor + friendly_name: Water Softener Salt Monitor + +esp8266: + board: d1_mini + +substitutions: + device_name: "Water Softener Salt Monitor" + device_id: salt_monitor + +# Enable logging +logger: + +# Enable Home Assistant API +api: + encryption: + key: !secret encryption_key + +ota: + password: !secret ota_password + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + fast_connect: true + + # Enable fallback hotspot (captive portal) in case wifi connection fails + ap: + ssid: "AP" + password: !secret ap_password + ap_timeout: 3min + +captive_portal: + +time: + - platform: homeassistant + id: homeassistant_time + timezone: America/Boise + +preferences: + # The default of 1min is far too short--flash chip is rated for approx 100k writes. + flash_write_interval: "48h" + +text_sensor: + - platform: version + name: "ESPHome Version" + + - platform: wifi_info + ip_address: + name: "IP" + ssid: + name: "SSID" + bssid: + name: "BSSID" + +button: + - platform: restart + name: "Restart" + +sensor: + - platform: uptime + name: "Uptime" + unit_of_measurement: h + filters: + - lambda: return int((x + 1800.0) / 3600.0); + + - platform: wifi_signal + name: "Wifi Signal" + update_interval: 5min + + - platform: ultrasonic + trigger_pin: D1 + echo_pin: D2 + name: "Salt level raw" + id: "${device_id}_raw" + update_interval: 1min + unit_of_measurement: "m" + filters: + - filter_out: nan + - sliding_window_moving_average: + window_size: 6 + send_every: 6 + + - platform: template + name: "Salt level" + state_class: measurement + icon: "mdi:percent" + update_interval: 5min + unit_of_measurement: "%" + # ((Salt Height - Bottom) * 100 / (Max - Bottom) + # Bottom should be the lowest level, usually the brine level. + lambda: return ((id(${device_id}_raw).state - 0.72) * 100) / (0.21 - 0.72); + + - platform: template + name: "Salt level cm" + device_class: distance + state_class: measurement + icon: "mdi:ruler" + update_interval: 5min + unit_of_measurement: "cm" + # (Tank Height - Salt Height) * 100 + lambda: return (0.93 - id(${device_id}_raw).state) * 100; diff --git a/packages/influxdb.yaml.disabled b/packages/influxdb.yaml.disabled index 03d9818b..bcad76fd 100644 --- a/packages/influxdb.yaml.disabled +++ b/packages/influxdb.yaml.disabled @@ -65,7 +65,7 @@ influxdb: # - update - weather # - zone - + # Filters for domains and entities to exclude from influxdb. # exclude: !include_dir_merge_named ../entities/influxdb exclude: diff --git a/packages/logger.yaml b/packages/logger.yaml index 9e943291..33c07bb8 100644 --- a/packages/logger.yaml +++ b/packages/logger.yaml @@ -8,32 +8,33 @@ logger: default: warn logs: homeassistant.loader: error - # custom_components.mail_and_packages: error - # homeassistant.core: warn - # homeassistant.components.automation: warn # homeassistant.components.climate.ecobee: error # homeassistant.components.device_tracker: error - # homeassistant.components.discovery: warn # homeassistant.components.ecobee: error + # Ignore AirNow connection errors homeassistant.components.airnow.coordinator: fatal # homeassistant.components.http: error homeassistant.components.media_player: error - # homeassistant.components.mqtt: warn + # MQTT naming warnings, remove when Hass.Agent is updated homeassistant.components.mqtt.mixins: error - # homeassistant.components.proximity: warn - # homeassistant.components.recorder: warn - # homeassistant.components.sensor.command_line: warn - # # homeassistant.components.shell_command: debug + # homeassistant.components.shell_command: debug # homeassistant.components.switch: error - # homeassistant.components.switch.command_line: warn - # homeassistant.components.twinkly.light: warn - # homeassistant.components.zha: warn - # homeassistant.components.zwave: warn - # homeassistant.helpers.entity: error - # homeassistant.helpers.script: warn - # bellows.ezsp: warn - # bellows.uart: warn - # # requests.packages.urllib3.connectionpool: critical - # zigpy.application: warn - # zigpy.zdo: warn - # filters: + # Quiet Trigger Update Coordinator + homeassistant.helpers.script.trigger_update_coordinator: error + # requests.packages.urllib3.connectionpool: critical + # Mail and packages + custom_components.mail_and_packages: error + + filters: + homeassistant: + - "Unclosed connection" + homeassistant.helpers.entity: + - "is taking over \\d+? seconds" + homeassistant.util.yaml.loader: + - "metro\\.yaml" + pychromecast.socket_client: + - "Heartbeat timeout" + - "Failed to connect" + pydreamscreen.devices: + - "get_state" + - "update state"