diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..a100dcb --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,14 @@ +name: pre-commit + +on: + pull_request: + push: + branches: [main] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + - uses: pre-commit/action@v3.0.0 diff --git a/.github/workflows/test_commit.yml b/.github/workflows/test_commit.yml new file mode 100644 index 0000000..89f5842 --- /dev/null +++ b/.github/workflows/test_commit.yml @@ -0,0 +1,22 @@ +name: Test Degree-Days + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + validate: + runs-on: "ubuntu-latest" + name: Validate HACS and Hassfest + steps: + - uses: "actions/checkout@v4" + + - name: HACS validation + uses: "hacs/action@main" + with: + category: "integration" + + - name: Hassfest validation + uses: "home-assistant/actions/hassfest@master" diff --git a/.ignore_words.txt b/.ignore_words.txt new file mode 100644 index 0000000..72f7014 --- /dev/null +++ b/.ignore_words.txt @@ -0,0 +1,3 @@ +als +hass +knmi diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..f5931ad --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,30 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: debug-statements + - id: check-builtin-literals + - id: check-case-conflict + - id: check-docstring-first + - id: check-json + - id: check-toml + - id: check-xml + - id: check-yaml + - id: detect-private-key + - id: end-of-file-fixer + - id: trailing-whitespace + - id: debug-statements +- repo: https://github.com/asottile/pyupgrade + rev: v2.37.3 + hooks: + - id: pyupgrade + args: [--py37-plus] +- repo: https://github.com/PyCQA/isort + rev: 5.12.0 + hooks: + - id: isort +- repo: https://github.com/codespell-project/codespell + rev: v2.1.0 + hooks: + - id: codespell + args: [--ignore-words=.ignore_words.txt] diff --git a/README.md b/README.md index 1618d79..7d57110 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # Degree-days integration -Degree days integration for Home Assistant based on KNMI weather station data (the Netherlands) and your current gas consumpition this year. +Degree days integration for Home Assistant based on KNMI weather station data (the Netherlands) and your current gas consumption this year. This integration will collect daily averaged temperatures of the last year from a KNMI weather station and will calculate the total number of (weighted) degree days this year (similar as is done on the [mindergas website](www.mindergas.nl)). Based on this information and input from your gas consumption so far this year, it will estimate the gas consumption for the entire year and will determine the gas consumption per weighted degree day, which can be used for comparison with other years or other houses. ## (Weighted) degree days -For more information on degree days and its use, have a look at the website [Degree Days.net](https://www.degreedays.net/) (English) or [Mindergas](https://mindergas.nl/degree_days/explanation) (Dutch). +For more information on degree days and its use, have a look at the website [Degree Days.net](https://www.degreedays.net/) (English) or [Mindergas](https://mindergas.nl/degree_days/explanation) (Dutch). In the current implementation, we follow the approach of Mindergas. Weighted degree days are determined by multiplying the number of degree days in a certain month with a certain factor. The applied multiplication factors are: @@ -19,11 +19,11 @@ You can add a gas sensor to calculate the gas consumption per weighted degree da ## How to install -1. Make sure you have [hacs](https://hacs.xyz/) installed +1. Make sure you have [hacs](https://hacs.xyz/) installed. 2. Add this repository as custom repository to hacs by going to hacs, integrations, click on the three dots in the upper right corner and click on custom repositories. -3. In the repository field, fill in the link to this repository (https://github.com/Ernst79/degree-days) and for category, select `Integration`. Click on `Add` -4. Go back to hacs, integrations and add click on the blue button `Exlore and download repositories` in the bottom left corner, search for `Degree-days` and install it -5. Reboot HA +3. In the repository field, fill in the link to this repository (https://github.com/Ernst79/degree-days) and for category, select `Integration`. Click on `Add`. +4. Go back to hacs, integrations and add click on the blue button `Exlore and download repositories` in the bottom left corner, search for `Degree-days` and install it. +5. Reboot HA. 6. In HA goto Config -> Integrations. Add the Degree-days integration to HA. 7. In your lovelace dashboard, add a card with the degree days entities. @@ -33,7 +33,7 @@ The Degree Days integration has the following options: **Weather station (KNMI)** -KNMI Weather station to get the daily mean outdoor temperatures. Currently only Dutch weather stations are supported. +KNMI Weather station to get the daily mean outdoor temperatures. Currently only Dutch weather stations are supported. **Mean indoor temperature** @@ -41,20 +41,24 @@ Estimated daily mean indoor temperature during day and night, averaged over one **Heating temperature limit** -In the spring and autumn, the heating will not always be turned on directly, even if the daily mean outdoor temperature is below the daily mean indoor temperature. Buildings will collect heat during hot periods in e.g. concrete walls, which is released gradually, preventing the heating to turn on. By setting a different heating temperature limit (e.g. 15,5°C), degree days will only be counted if the daily mean outdoor temperature is lower than this heating temperature limit. A lower value for the heating temperature will increase the gas consumption per degree day in the spring and autumn. +In the spring and autumn, the heating will not always be turned on directly, even if the daily mean outdoor temperature is below the daily mean indoor temperature. Buildings will collect heat during hot periods in e.g. concrete walls, which is released gradually, preventing the heating to turn on. By setting a different heating temperature limit (e.g. 15,5°C), degree days will only be counted if the daily mean outdoor temperature is lower than this heating temperature limit. A lower value for the heating temperature will increase the gas consumption per degree day in the spring and autumn. **Startday for sum of total degree days** -Day of the month from which the yearly totals are computed. When used in combination with a gas sensor, this has to be the same day as the total gas consumption is determined from. E.g. if your gas sensor reports the total gas consumption starting at the 14th of February, set the Startday for the sum of total degree days to the 14th. +Day of the month from which the yearly totals are computed. When used in combination with a gas sensor, this has to be the same day as the total gas consumption is determined from. E.g. if your gas sensor reports the total gas consumption starting at the 14th of February, set the Startday for the sum of total degree days to the 14th. **Startmonth for sum of total degree days** -Month from which the yearly totals are computed. When used in combination with a gas sensor, this has to be the same month as the total gas consumption is determined from. E.g. if your gas sensor reports the total gas consumption starting at the 14th of February, set the Startmonth for the sum of total degree days to the February. +Month from which the yearly totals are computed. When used in combination with a gas sensor, this has to be the same month as the total gas consumption is determined from. E.g. if your gas sensor reports the total gas consumption starting at the 14th of February, set the Startmonth for the sum of total degree days to the February. -**Gas sensor entity** +**Gas/Energy sensor entity** -Gas sensor entity with the total consumption of gas in m3, starting at the set Startday and Startmonth of the current year. +Gas/Energy sensor entity with the total consumption of gas in m3 or Energy in kWh, starting at the set Startday and Startmonth of the current year. -**Monthly gas usage for shower, bath and cooking** +**Monthly gas/energy usage for shower, bath and cooking** -Monthly gas usage for shower, bath and cooking. This will be substracted from your gas consumption, before calculating the gas usage per weighted degree day. +Monthly gasenergy usage for shower, bath and cooking. This will be subtracted from your gas consumption, before calculating the gas usage per weighted degree day. + +**Heatpump/Electric heating** + +Enable this option if you want to use kWh instead of m3, e.g. when you use a heatpump. diff --git a/custom_components/degree_days/__init__.py b/custom_components/degree_days/__init__.py index 2665233..3643860 100644 --- a/custom_components/degree_days/__init__.py +++ b/custom_components/degree_days/__init__.py @@ -1,36 +1,22 @@ """Degree Days integration.""" -from datetime import timedelta import datetime import logging - -from .knmi import KNMI -from requests.exceptions import HTTPError, Timeout +from datetime import timedelta from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers import update_coordinator +from requests.exceptions import HTTPError, Timeout -from .const import ( - CONF_HEATING_LIMIT, - CONF_INDOOR_TEMP, - CONF_WEATHER_STATION, - CONF_STARTDAY, - CONF_STARTMONTH, - CONF_CONSUMPTION_SENSOR, - CONF_DHW_CONSUMPTION, - CONF_HEATPUMP, - CONF_GAS_SENSOR, - CONF_GAS_USE_OTHER, - DEFAULT_HEATING_LIMIT, - DEFAULT_INDOOR_TEMP, - DEFAULT_WEATHER_STATION, - DEFAULT_STARTDAY, - DEFAULT_STARTMONTH, - DEFAULT_CONSUMPTION_SENSOR, - DEFAULT_DHW_CONSUMPTION, - DEFAULT_HEATPUMP, - DOMAIN -) +from .const import (CONF_CONSUMPTION_SENSOR, CONF_DHW_CONSUMPTION, + CONF_GAS_SENSOR, CONF_GAS_USE_OTHER, CONF_HEATING_LIMIT, + CONF_HEATPUMP, CONF_INDOOR_TEMP, CONF_STARTDAY, + CONF_STARTMONTH, CONF_WEATHER_STATION, + DEFAULT_CONSUMPTION_SENSOR, DEFAULT_DHW_CONSUMPTION, + DEFAULT_HEATING_LIMIT, DEFAULT_HEATPUMP, + DEFAULT_INDOOR_TEMP, DEFAULT_STARTDAY, DEFAULT_STARTMONTH, + DEFAULT_WEATHER_STATION, DOMAIN) +from .knmi import KNMI _LOGGER = logging.getLogger(__name__) @@ -133,8 +119,6 @@ def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None: async def _async_update_data(self): """Update the data from the KNMI device.""" - - # Get consumption state try: self.total_consumption_sensor_state = self.hass.states.get(self.total_consumption_sensor) self.total_consumption = float(self.total_consumption_sensor_state.state) diff --git a/custom_components/degree_days/config_flow.py b/custom_components/degree_days/config_flow.py index 1a9bd21..97d0709 100644 --- a/custom_components/degree_days/config_flow.py +++ b/custom_components/degree_days/config_flow.py @@ -3,32 +3,17 @@ import logging import voluptuous as vol - from homeassistant import config_entries from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import config_validation as cv -from .const import ( - CONF_CONSUMPTION_SENSOR, - CONF_DHW_CONSUMPTION, - CONF_HEATING_LIMIT, - CONF_HEATPUMP, - CONF_INDOOR_TEMP, - CONF_STARTDAY, - CONF_STARTMONTH, - CONF_WEATHER_STATION, - DEFAULT_CONSUMPTION_SENSOR, - DEFAULT_DHW_CONSUMPTION, - DEFAULT_HEATING_LIMIT, - DEFAULT_HEATPUMP, - DEFAULT_INDOOR_TEMP, - DEFAULT_STARTDAY, - DEFAULT_STARTMONTH, - DEFAULT_WEATHER_STATION, - DOMAIN, - MONTHS, - STATION_MAPPING -) +from .const import (CONF_CONSUMPTION_SENSOR, CONF_DHW_CONSUMPTION, + CONF_HEATING_LIMIT, CONF_HEATPUMP, CONF_INDOOR_TEMP, + CONF_STARTDAY, CONF_STARTMONTH, CONF_WEATHER_STATION, + DEFAULT_CONSUMPTION_SENSOR, DEFAULT_DHW_CONSUMPTION, + DEFAULT_HEATING_LIMIT, DEFAULT_HEATPUMP, + DEFAULT_INDOOR_TEMP, DEFAULT_STARTDAY, DEFAULT_STARTMONTH, + DEFAULT_WEATHER_STATION, DOMAIN, MONTHS, STATION_MAPPING) _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/degree_days/const.py b/custom_components/degree_days/const.py index ef48786..42b7336 100644 --- a/custom_components/degree_days/const.py +++ b/custom_components/degree_days/const.py @@ -3,16 +3,10 @@ from dataclasses import dataclass -from homeassistant.components.sensor import ( - SensorDeviceClass, - SensorEntityDescription, - SensorStateClass, -) -from homeassistant.const import ( - UnitOfEnergy, - UnitOfTemperature, - UnitOfVolume, -) +from homeassistant.components.sensor import (SensorDeviceClass, + SensorEntityDescription, + SensorStateClass) +from homeassistant.const import UnitOfEnergy, UnitOfTemperature, UnitOfVolume from homeassistant.util import dt DOMAIN = "degree_days" @@ -66,7 +60,7 @@ 'Lauwersoog': 277, 'Leeuwarden': 270, 'Lelystad': 269, - 'Maastricht': 380, + 'Maastricht': 380, 'Marknesse': 273, 'Nieuw Beerta': 286, 'Oosterschelde': 312, diff --git a/custom_components/degree_days/knmi/__init__.py b/custom_components/degree_days/knmi/__init__.py index 55a0926..2e8179d 100644 --- a/custom_components/degree_days/knmi/__init__.py +++ b/custom_components/degree_days/knmi/__init__.py @@ -1,14 +1,15 @@ """Module to calculate the (weighted) degree days from KNMI data""" from datetime import datetime from io import StringIO -import requests + import pandas as pd +import requests from ..const import STATION_MAPPING, WEIGHT_FACTOR -class KNMI(object): - """KMNI datas""" +class KNMI: + """KMNI data""" def __init__(self, startdate, station, T_indoor, T_heatinglimit, total_consumption, dhw_consumption, heatpump): self.startdate = startdate self.station = station diff --git a/custom_components/degree_days/manifest.json b/custom_components/degree_days/manifest.json index 19aa03a..05f5b7e 100644 --- a/custom_components/degree_days/manifest.json +++ b/custom_components/degree_days/manifest.json @@ -1,8 +1,8 @@ { "domain": "degree_days", "name": "Degree-Days", - "config_flow": true, "codeowners": ["@Ernst79", "@nelbs"], + "config_flow": true, "dependencies": [], "documentation": "https://www.home-assistant.io/integrations/degree_days", "iot_class": "cloud_polling", @@ -10,4 +10,3 @@ "requirements": [], "version": "1.0.1" } - diff --git a/custom_components/degree_days/sensor.py b/custom_components/degree_days/sensor.py index 1269cd9..c533a19 100644 --- a/custom_components/degree_days/sensor.py +++ b/custom_components/degree_days/sensor.py @@ -4,13 +4,8 @@ from homeassistant.helpers.entity import StateType from . import DegreeDaysData -from .const import ( - DOMAIN, - GAS_SENSOR_TYPES, - HEATPUMP_SENSOR_TYPES, - SENSOR_TYPES, - DegreeDaysSensorEntityDescription -) +from .const import (DOMAIN, GAS_SENSOR_TYPES, HEATPUMP_SENSOR_TYPES, + SENSOR_TYPES, DegreeDaysSensorEntityDescription) async def async_setup_entry(hass, entry, async_add_entities): diff --git a/hacs.json b/hacs.json index 97f2381..8d32c7b 100644 --- a/hacs.json +++ b/hacs.json @@ -1,7 +1,5 @@ - { "name": "Degree-Days integration", - "domains": "degree_days", "render_readme": true, - "homeassistant": "2021.10.0" + "homeassistant": "2023.12.0" }