diff --git a/.github/workflows/build-firmware.yaml b/.github/workflows/build-firmware.yaml new file mode 100644 index 00000000..c93fa3f1 --- /dev/null +++ b/.github/workflows/build-firmware.yaml @@ -0,0 +1,165 @@ +--- +# Build the ESPHome firmwares for the Home Assistant Glow project. +name: Build firmware + +on: + push: + branches: + - main + workflow_dispatch: + pull_request: + # release: + # types: + # - published + schedule: + - cron: "0 5 * * 1" + +concurrency: + # yamllint disable-line rule:line-length + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + FIRMWARES: home-assistant-glow + +jobs: + prepare: + name: Prepare matrix + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.prepare-matrix.outputs.matrix }} + steps: + - name: ⤵️ Check out code from GitHub + uses: actions/checkout@v4 + - name: Get changed files + id: changes + uses: masesgroup/retrieve-changed-files@v3 + if: github.event_name == 'pull_request' + - name: Prepare matrix + id: prepare-matrix + run: |- + # Set variables + matrix="" + fullRun=$(! [[ "${{ github.event_name }}" != "pull_request" || "${{ steps.changes.outputs.modified }}" == *".github/workflows/build-firmware.yaml"* ]]; echo $?) + + # Iterate through firmwares and devices + for firmware in $FIRMWARES; do + for device in $firmware/*.yaml; do + # If pull_request event type and changed files do not contain the device, skip it + if [[ $fullRun -eq 0 && "${{ steps.changes.outputs.added_modified }}" != *"${device}"* ]]; then + continue + fi + + # Extract device name from file path + device=${device##*/} + device=${device%.yaml} + + # Set default version + version="latest" + + # Build matrix entry + matrix="$matrix{\"firmware\":\"$firmware\",\"device\":\"$device\", \"version\":\"$version\"}," + done + done + + # Remove trailing comma and format matrix + matrix=${matrix%?} + matrix="{\"include\":[$matrix]}" + + # Output matrix to a file + echo matrix=$matrix >> $GITHUB_OUTPUT + + build: + name: ${{ matrix.firmware }} / ${{ matrix.device }} + runs-on: ubuntu-latest + needs: prepare + strategy: + max-parallel: 5 + fail-fast: false + matrix: ${{fromJson(needs.prepare.outputs.matrix)}} + steps: + - name: ⤵️ Check out code from GitHub + uses: actions/checkout@v4 + - name: 🔨 Build firmware + uses: esphome/build-action@v1.8.0 + id: esphome-build + with: + yaml_file: ${{ matrix.firmware }}/${{ matrix.device }}.yaml + version: ${{ matrix.version || 'latest' }} + - name: Move generated files to output + run: | + mkdir -p output/${{ matrix.device }} + mv ${{ steps.esphome-build.outputs.name }}/* output/${{ matrix.device }}/ + echo ${{ steps.esphome-build.outputs.version }} > output/${{ matrix.device }}/version + - name: Alter manifest path + run: | + sed -i 's/${{ steps.esphome-build.outputs.name }}\//\/${{ matrix.firmware }}\/${{ matrix.device }}\//g' output/${{ matrix.device }}/manifest.json + - name: ⬆️ Upload firmware artifact + uses: actions/upload-artifact@v3.1.3 + with: + name: ${{ matrix.firmware}} + path: output + + combined-manifests: + name: Combine ${{ matrix.project }} manifests + if: (github.event_name == 'workflow_dispatch' || github.event_name == 'push') && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + needs: build + strategy: + fail-fast: false + matrix: + include: + - project: home-assistant-glow + name: Home Assistant Glow + steps: + - name: ⤵️ Download artifacts + uses: actions/download-artifact@v3 + with: + name: ${{ matrix.project }} + path: files + - name: Generate manifest.json + run: | + version=$(cat files/*/version | sort -V | tail -n 1) + jq -s --arg version "$version" '{"name": "${{ matrix.name }}", "version": $version, "home_assistant_domain": "esphome", "builds":.}' files/*/manifest.json > manifest.json + - name: ⬆️ Upload manifest.json + uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.project }} + path: manifest.json + + consolidate: + name: Consolidate firmwares + if: (github.event_name == 'workflow_dispatch' || github.event_name == 'push') && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + needs: combined-manifests + steps: + - name: ⤵️ Check out code from GitHub + uses: actions/checkout@v4 + - name: ⬇️ Download artifacts + uses: actions/download-artifact@v3 + with: + path: output + - name: Copy static files + run: cp -R static/* output/ + - name: ⬆️ Upload output artifacts + uses: actions/upload-artifact@v3 + with: + path: output + + deploy: + name: Deploy to GitHub Pages + if: (github.event_name == 'workflow_dispatch' || github.event_name == 'push') && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + needs: consolidate + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Setup Github Pages + uses: actions/configure-pages@v4 + - name: 🚀 Deploy to Github Pages + uses: actions/deploy-pages@v3.0.1 + id: deployment diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml deleted file mode 100644 index 85dd9329..00000000 --- a/.github/workflows/ci.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -# Can we build firmware check -name: CI - -on: - pull_request: - -jobs: - ci: - name: "🛠️ Build check" - runs-on: ubuntu-latest - steps: - - name: ⤵️ Check out files from GitHub - uses: actions/checkout@v3 - - name: Test firmware build - uses: esphome/build-action@v1.8.0 - with: - yaml_file: home_assistant_glow.yaml diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml deleted file mode 100644 index 7e7a854b..00000000 --- a/.github/workflows/publish.yaml +++ /dev/null @@ -1,18 +0,0 @@ ---- -# Build the ESPHome binary firmware -# And deploy it to Github Pages. -name: Publish firmware - -on: - workflow_dispatch: - release: - types: - - published - -jobs: - publish: - name: "🛠️ ESPHome firmware" - uses: esphome/workflows/.github/workflows/publish.yml@main - with: - files: home_assistant_glow.yaml - name: Home Assistant Glow diff --git a/components/basis.yaml b/components/basis.yaml new file mode 100644 index 00000000..ce036e92 --- /dev/null +++ b/components/basis.yaml @@ -0,0 +1,41 @@ +# Basic configuration # +button: + # Restart the ESP + - platform: restart + name: "Restart - Glow" + +# Sensors for ESP version and WIFI information +text_sensor: + # Installed version + - platform: template + name: "Glow - Installed version" + id: glow_version + icon: "mdi:label-outline" + entity_category: diagnostic + lambda: |- + return {"${project_version}"}; + update_interval: 6h + # ESPHome version + - platform: version + hide_timestamp: true + name: '${friendly_name} - ESPHome Version' + # IP address and connected SSID + - platform: wifi_info + ip_address: + name: '${friendly_name} - IP Address' + icon: mdi:wifi + ssid: + name: '${friendly_name} - Connected SSID' + icon: mdi:wifi-strength-2 + +sensor: + # WiFi signal + - platform: wifi_signal + name: "${friendly_name} - WiFi Signal" + update_interval: 120s + +# Enable time component to reset energy at midnight +# https://esphome.io/components/time/homeassistant.html +time: + - platform: homeassistant + id: homeassistant_time \ No newline at end of file diff --git a/components/pulse_meter.yaml b/components/pulse_meter.yaml new file mode 100644 index 00000000..4956cfac --- /dev/null +++ b/components/pulse_meter.yaml @@ -0,0 +1,107 @@ +# Pulse meter configuration # + +# Enable Home Assistant API +api: + services: + - service: reset_total_energy + then: + - button.press: + id: button_reset_total + +number: + # Set the pulse rate of the LED on your meter + - platform: template + id: select_pulse_rate + name: 'Puls rate - imp/kWh' + optimistic: true + mode: box + min_value: 100 + max_value: 10000 + step: 100 + restore_value: yes + initial_value: 1000 + + # Reset total energy to given value + - platform: template + id: select_reset_total + name: 'Reset Value - Total Energy kWh' + entity_category: config + optimistic: true + mode: box + min_value: 0 + max_value: 1000000 + step: 1 + initial_value: 0 + +button: + # Reset the total energy entity + - platform: template + name: "Reset - Total Energy" + id: button_reset_total + on_press: + - pulse_meter.set_total_pulses: + id: sensor_energy_pulse_meter + value: !lambda "return id(select_reset_total).state * id(select_pulse_rate).state;" + +sensor: + # Pulse meter + - platform: pulse_meter + name: '${friendly_name} - Power Consumption' + id: sensor_energy_pulse_meter + unit_of_measurement: W + state_class: measurement + device_class: power + icon: mdi:flash-outline + accuracy_decimals: 0 + pin: ${pulse_pin} + # internal_filter: 100ms + on_raw_value: + then: + - light.turn_on: + id: led_red + - delay: 0.2s + - light.turn_off: + id: led_red + filters: + # multiply value = (60 / imp value) * 1000 + # - multiply: 60 + - lambda: return x * ((60.0 / id(select_pulse_rate).state) * 1000.0); + + # Update the sensor with an average every 10th second. See + # https://github.com/klaasnicolaas/home-assistant-glow/#reduce-the-amount-of-data-the-sensors-produce + # for more information. + #- throttle_average: 10s + #- filter_out: NaN + + total: + name: '${friendly_name} - Total Energy' + id: sensor_total_energy + unit_of_measurement: kWh + icon: mdi:circle-slice-3 + state_class: total_increasing + device_class: energy + accuracy_decimals: 3 + filters: + # multiply value = 1 / imp value + # - multiply: 0.001 + - lambda: return x * (1.0 / id(select_pulse_rate).state); + + # Update the sensor once per 0.1 kWh consumed, or every 5th minute, whichever happens sooner. + # See https://github.com/klaasnicolaas/home-assistant-glow/#reduce-the-amount-of-data-the-sensors-produce + # for more information. + #- delta: 0.01 + #- heartbeat: 300s + + # Total day usage + - platform: total_daily_energy + name: '${friendly_name} - Daily Energy' + id: sensor_total_daily_energy + power_id: sensor_energy_pulse_meter + unit_of_measurement: kWh + icon: mdi:circle-slice-3 + state_class: total_increasing + device_class: energy + accuracy_decimals: 3 + filters: + # Multiplication factor from W to kW is 0.001 + - multiply: 0.001 \ No newline at end of file diff --git a/components/status_led.yaml b/components/status_led.yaml new file mode 100644 index 00000000..875bfaec --- /dev/null +++ b/components/status_led.yaml @@ -0,0 +1,24 @@ +# Status LED configuration # +output: + # - platform: gpio + # pin: GPIO5 + # id: output_blue + - platform: gpio + pin: ${led_pin_red} + id: output_red + - platform: gpio + pin: ${led_pin_green} + id: output_green + +light: + - platform: binary + internal: true + id: led_red + name: Red + output: output_red + +# Status LED for connection +status_led: + pin: + # Blue LED + number: ${status_led} \ No newline at end of file diff --git a/home-assistant-glow/d1_mini.yaml b/home-assistant-glow/d1_mini.yaml new file mode 100644 index 00000000..eda1a608 --- /dev/null +++ b/home-assistant-glow/d1_mini.yaml @@ -0,0 +1,60 @@ +--- +# Home Assistant Glow +# +# Read your electricity meter by means of the pulse LED on your +# meter, useful if you do not have a serial port (P1). +# © Klaas Schoute +# +substitutions: + device_name: home-assistant-glow + friendly_name: Home Assistant Glow + project_version: "4.0.0" + device_description: "Measure your energy consumption with the pulse LED on your smart meter - Wemos D1 Mini" + + # Define the GPIO pins + pulse_pin: GPIO13 + status_led: GPIO5 + led_pin_red: GPIO2 + led_pin_green: GPIO4 + +esphome: + name: '${device_name}' + comment: '${device_description}' + project: + name: "klaasnicolaas.home-assistant-glow" + version: "${project_version}" + +dashboard_import: + package_import_url: github://klaasnicolaas/home-assistant-glow/home-assistant-glow/esp32.yaml@main + +esp8266: + board: d1_mini + +packages: + basis: !include ../components/basis.yaml + status_led: !include ../components/status_led.yaml + pulse_meter: !include ../components/pulse_meter.yaml + +# Enable logging +logger: + +# Allow OTA updates +ota: + safe_mode: true + reboot_timeout: 10min + num_attempts: 5 + +# Allow provisioning Wi-Fi via serial +improv_serial: + +wifi: + # Set up a wifi access point + ap: + ssid: '${friendly_name}' + +# In combination with the `ap` this allows the user +# to provision wifi credentials to the device via WiFi AP. +captive_portal: + +# To have a "next url" for improv serial +web_server: diff --git a/home-assistant-glow/esp32.yaml b/home-assistant-glow/esp32.yaml new file mode 100644 index 00000000..c5a180f1 --- /dev/null +++ b/home-assistant-glow/esp32.yaml @@ -0,0 +1,60 @@ +--- +# Home Assistant Glow +# +# Read your electricity meter by means of the pulse LED on your +# meter, useful if you do not have a serial port (P1). +# © Klaas Schoute +# +substitutions: + device_name: home-assistant-glow + friendly_name: Home Assistant Glow + project_version: "4.0.0" + device_description: "Measure your energy consumption with the pulse LED on your smart meter - ESP32" + + # Define the GPIO pins + pulse_pin: GPIO13 + status_led: GPIO5 + led_pin_red: GPIO2 + led_pin_green: GPIO4 + +esphome: + name: '${device_name}' + comment: '${device_description}' + project: + name: "klaasnicolaas.home-assistant-glow" + version: "${project_version}" + +dashboard_import: + package_import_url: github://klaasnicolaas/home-assistant-glow/home-assistant-glow/esp32.yaml@main + +esp32: + board: nodemcu-32s + +packages: + basis: !include ../components/basis.yaml + status_led: !include ../components/status_led.yaml + pulse_meter: !include ../components/pulse_meter.yaml + +# Enable logging +logger: + +# Allow OTA updates +ota: + safe_mode: true + reboot_timeout: 10min + num_attempts: 5 + +# Allow provisioning Wi-Fi via serial +improv_serial: + +wifi: + # Set up a wifi access point + ap: + ssid: '${friendly_name}' + +# In combination with the `ap` this allows the user +# to provision wifi credentials to the device via WiFi AP. +captive_portal: + +# To have a "next url" for improv serial +web_server: \ No newline at end of file diff --git a/home-assistant-glow/esp8266.yaml b/home-assistant-glow/esp8266.yaml new file mode 100644 index 00000000..c8dad134 --- /dev/null +++ b/home-assistant-glow/esp8266.yaml @@ -0,0 +1,60 @@ +--- +# Home Assistant Glow +# +# Read your electricity meter by means of the pulse LED on your +# meter, useful if you do not have a serial port (P1). +# © Klaas Schoute +# +substitutions: + device_name: home-assistant-glow + friendly_name: Home Assistant Glow + project_version: "4.0.0" + device_description: "Measure your energy consumption with the pulse LED on your smart meter - ESP8266" + + # Define the GPIO pins + pulse_pin: GPIO13 + status_led: GPIO5 + led_pin_red: GPIO2 + led_pin_green: GPIO4 + +esphome: + name: '${device_name}' + comment: '${device_description}' + project: + name: "klaasnicolaas.home-assistant-glow" + version: "${project_version}" + +dashboard_import: + package_import_url: github://klaasnicolaas/home-assistant-glow/home-assistant-glow/esp32.yaml@main + +esp8266: + board: nodemcuv2 + +packages: + basis: !include ../components/basis.yaml + status_led: !include ../components/status_led.yaml + pulse_meter: !include ../components/pulse_meter.yaml + +# Enable logging +logger: + +# Allow OTA updates +ota: + safe_mode: true + reboot_timeout: 10min + num_attempts: 5 + +# Allow provisioning Wi-Fi via serial +improv_serial: + +wifi: + # Set up a wifi access point + ap: + ssid: '${friendly_name}' + +# In combination with the `ap` this allows the user +# to provision wifi credentials to the device via WiFi AP. +captive_portal: + +# To have a "next url" for improv serial +web_server: diff --git a/home_assistant_glow.yaml b/home_assistant_glow.yaml deleted file mode 100644 index 7e9d2af0..00000000 --- a/home_assistant_glow.yaml +++ /dev/null @@ -1,234 +0,0 @@ ---- -# Home Assistant Glow -# -# Read your electricity meter by means of the pulse LED on your -# meter, useful if you do not have a serial port (P1). -# © Klaas Schoute -# -substitutions: - device_name: home-assistant-glow - friendly_name: House - project_version: "4.0.0" - device_description: "Measure your energy consumption with the pulse LED on your smart meter" - - # Define the GPIO pins - pulse_pin: GPIO13 - status_led: GPIO5 - led_pin_red: GPIO2 - led_pin_green: GPIO4 - - # Webserver credentials ⬇ # - web_username: 'glow' - web_password: 'esphome' - -dashboard_import: - package_import_url: github://klaasnicolaas/home-assistant-glow/home_assistant_glow.yaml@main - -esphome: - name: '${device_name}' - comment: '${device_description}' - project: - name: "klaasnicolaas.home-assistant-glow" - version: "${project_version}" - -# Choose the right Platform -# esp32: https://esphome.io/components/esp32.html -# esp8266: https://esphome.io/components/esp8266.html -esp32: - board: nodemcu-32s - -# WiFi credentials # -wifi: - # ssid: 'CHANGEME' - # password: 'CHANGEME' - - # Enable fallback hotspot (captive portal) in case wifi connection fails - ap: - ssid: '${device_name}' - -captive_portal: - -# Enable logging -logger: - -# Enable improv over serial -improv_serial: - -# Enable Home Assistant API -api: - services: - - service: reset_total_energy - then: - - button.press: - id: button_reset_total - -ota: - safe_mode: true - reboot_timeout: 10min - num_attempts: 5 - -web_server: - port: 80 - auth: - username: '${web_username}' - password: '${web_password}' - -number: - # Select the correct pulse rate for your meter - - platform: template - id: select_pulse_rate - name: 'Puls rate - imp/kWh' - optimistic: true - mode: box - min_value: 100 - max_value: 10000 - step: 100 - restore_value: yes - initial_value: 1000 - - # Reset total energy to given value - - platform: template - id: select_reset_total - name: "Reset Value - Total Energy kWh" - entity_category: config - optimistic: true - mode: box - min_value: 0 - max_value: 1000000 - step: 1 - initial_value: 0 - -output: - # - platform: gpio - # pin: GPIO5 - # id: output_blue - - platform: gpio - pin: ${led_pin_red} - id: output_red - - platform: gpio - pin: ${led_pin_green} - id: output_green - -light: - - platform: binary - internal: true - id: led_red - name: Red - output: output_red - -# Status LED for connection -status_led: - pin: - # Blue LED - number: ${status_led} - -button: - # Restart the ESP - - platform: restart - name: "Restart - Glow" - # Reset the total energy entity - - platform: template - name: "Reset - Total Energy" - id: button_reset_total - on_press: - - pulse_meter.set_total_pulses: - id: sensor_energy_pulse_meter - value: !lambda "return id(select_reset_total).state * id(select_pulse_rate).state;" - -# Sensors for ESP version and WIFI information -text_sensor: - # Installed version - - platform: template - name: "Glow - Installed version" - id: glow_version - icon: "mdi:label-outline" - entity_category: diagnostic - lambda: |- - return {"${project_version}"}; - update_interval: 6h - # ESPHome version - - platform: version - hide_timestamp: true - name: '${friendly_name} - ESPHome Version' - # IP address and connected SSID - - platform: wifi_info - ip_address: - name: '${friendly_name} - IP Address' - icon: mdi:wifi - ssid: - name: '${friendly_name} - Connected SSID' - icon: mdi:wifi-strength-2 - -sensor: - # WiFi signal - - platform: wifi_signal - name: "${friendly_name} - WiFi Signal" - update_interval: 120s - - # Pulse meter - - platform: pulse_meter - name: '${friendly_name} - Power Consumption' - id: sensor_energy_pulse_meter - unit_of_measurement: 'W' - state_class: measurement - device_class: power - icon: mdi:flash-outline - accuracy_decimals: 0 - pin: ${pulse_pin} - # internal_filter: 100ms - on_raw_value: - then: - - light.turn_on: - id: led_red - - delay: 0.2s - - light.turn_off: - id: led_red - filters: - # multiply value = (60 / imp value) * 1000 - # - multiply: 60 - - lambda: return x * ((60.0 / id(select_pulse_rate).state) * 1000.0); - - # Update the sensor with an average every 10th second. See - # https://github.com/klaasnicolaas/home-assistant-glow/#reduce-the-amount-of-data-the-sensors-produce - # for more information. - #- throttle_average: 10s - #- filter_out: NaN - - total: - name: '${friendly_name} - Total Energy' - id: sensor_total_energy - unit_of_measurement: 'kWh' - icon: mdi:circle-slice-3 - state_class: total_increasing - device_class: energy - accuracy_decimals: 3 - filters: - # multiply value = 1 / imp value - # - multiply: 0.001 - - lambda: return x * (1.0 / id(select_pulse_rate).state); - - # Update the sensor once per 0.1 kWh consumed, or every 5th minute, whichever happens sooner. - # See https://github.com/klaasnicolaas/home-assistant-glow/#reduce-the-amount-of-data-the-sensors-produce - # for more information. - #- delta: 0.01 - #- heartbeat: 300s - - # Total day usage - - platform: total_daily_energy - name: '${friendly_name} - Daily Energy' - id: sensor_total_daily_energy - power_id: sensor_energy_pulse_meter - unit_of_measurement: 'kWh' - icon: mdi:circle-slice-3 - state_class: total_increasing - device_class: energy - accuracy_decimals: 3 - filters: - # Multiplication factor from W to kW is 0.001 - - multiply: 0.001 - -# Enable time component to reset energy at midnight -# https://esphome.io/components/time/homeassistant.html -time: - - platform: homeassistant - id: homeassistant_time