The novafos
component is a Home Assistant custom component for monitoring your water metering data from Novafos (via KMD Easy-Energy)
novafos
sensor.novafos
integration.novafos
sensor.Fully configurable through config flow.
Municipality | supplier id |
---|---|
Allerød | 0642000 |
Ballerup | 0618000 |
Egedal | 0378000 |
Furesø | 0378000 |
Frederikssund | 0642000 |
Gentofte | 0676000 |
Gladsaxe | 0676000 |
Hørsholm | 0398000 |
Rudersdal | 0642000 |
If your municipality isn't listed above, try one of these methods:
In chrome press F12, and select the "Network" tab. Login on the https://minforsyning-2.kmd.dk webpage. Inspect the first few entries. You should see something along the lines of: https://<7-digit number>.webtools.kmd.dk/wts/... The 7 digit number is your supplier ID.
In chrome press F12, and select the "Network" tab. Login on https://novafos.dk/selvbetjening/mit-forbrug using the "Klik her og login" button Login using nemID, and look for the request "ExternalLogin?returnUrl...." Inspect the "Headers" tab and under "General" -> "Request URL" you should see a parameter in the URL "...utility=<7-digit number>&...." The 7 digit number is your supplier ID
Novafos and probably other suppliers changed their login page to use a hidden reCAPTCHA. The very purpose of reCAPTCHA is to tell humans and machines apart. The effect of this little change is that the plugin is basically rendered useless except for the two workarounds implemented. Both workarounds utilise that after proper authentication a session token is handed out to access the data API.
This is your data. If you want to ensure free and opensource access to your data in your own home, please help KMD realise there is a need for this. Sure the claim can be that you have free access to your data through the portal, and even through the Watts app only available on mobile devices. These are all closed source solutions however, and eliminates homegrown solutions like Home Assistant to thrive.
If you use the integration please write to KMD Easy-energy, or call their contact number to ask for this. You can even give an example of where this actually works by referring to eloverblik.dk where a personal access token can be generated and used by your own tools.
Until KMD Easy-energy agrees to provide open access to your own data, the integration needs a little help now and then.
This first method is 100% manual, but will ensure you get data into Home Assistant regardless. Why would you do this then? Well I cannot say, but maybe doing this once per week or month is a good way to keep tabs on consumption or dripping faucets along with all yout other precious data.
This is how the manual method works:
{
"access_token": "<token>",
"token_type": "Bearer",
"expires_in": 3599,
"scope": "openid profile pluginapi_int",
"id_token": "<id token>"
}
access_token
part into the Access Token field (this is a very long string of random characters)If you try this method, please bear in mind it is an attempt to automate that which cannot be automated. Also accept that this is targeted at how the Novafos login page looks like and may need modifications for other suppliers' login screens. Lastly, I cannot support you if it does not work, you need to debug and help out with more endpoints which looks differently.
This is work in progress too, provided as-is and works-for-me.
With that said...
The principle is to software control the normal login process you would do on the website, and let the browser resolve that part of the process including robot detection. The software attempts to not look like a robot, and rests on very seldom access because only once per 24h is access really needed. Combined this hopefully is enough to not get caught in the robot detection heuristics.
What you need to do:
You need a docker host and access to build a docker image
Build the docker container using the Dockerfile
in the docker
directory
docker build -t ha/ha-pyapi:1.0 .
Run the docker container
docker run --name pyapi -p 5000:5000 -p 5900:5900 ha/ha-pyapi:1.0
If you stop the container for rebuilding you need to remove the old one before starting a new one
docker rm pyapi
With this container running you now have two endpoints available on http://<docker_host>:5000/novafos-token
and http://<docker_host>:5000/novafos-token-test
. Additionally you have a VNC service running on port 5900
. The VNC password is "secret"
You then need to modify the coordinator.py
file. Search for selenium_host_url
and update to match your IP-address of the docker host.
By the way - if you are lazy, you may try out the docker-compose file instead.
The first test uses the test end-point with a token you put in, and serves the purpose of verifying the container runs as intended and Home Assistant can access it properly.
Begin with the novafos-token-test
URL and update the pyapi.py
file with a token you got from using Method 1 above. Rebuild the container after doing this.
Bring up your (test) instance of Home Assistant with full debugging info activated and observe the log. You are looking for
2022-10-17 00:22:42 DEBUG (MainThread) [custom_components.novafos] Novafos ConfigData: {'supplierid': '<...', 'username': '<...>', 'password': '<...>', 'name': 'Novafos'} 2022-10-17 00:22:42 DEBUG (MainThread) [custom_components.novafos.coordinator] Next update at: 2022-10-18 03:03:00.189765
If the token you put in at the test endpoint is still okay (remember 1 hour validity) you should shortly after see the initial poll after a restart:
2022-10-17 00:23:05 DEBUG (SyncWorker_3) [custom_components.novafos.pynovafos.novafos] Got bearer token (access to API was Ok) valid for 3599s: Bearer eyLotsOfRandomCharcters... 2022-10-17 00:23:05 DEBUG (SyncWorker_2) [custom_components.novafos.pynovafos.novafos] Retrieved customer_id: <...> 2022-10-17 00:23:06 DEBUG (SyncWorker_2) [custom_components.novafos.pynovafos.novafos] Got active (water) meters : [{'InstallationId': <...>, 'MeasurementPointId': <...>, 'Unit': {'Id': <...>, 'Name': 'm³', 'Description': 'Vand', 'Decimals': 0, 'Order': 1}}] 2022-10-17 00:23:06 DEBUG (SyncWorker_2) [custom_components.novafos.pynovafos.novafos] Getting Day data from 2022-10-01T00:00:00.000Z to 2022-10-31T00:00:00.000Z 2022-10-17 00:23:06 DEBUG (SyncWorker_2) [custom_components.novafos.pynovafos.novafos] { "SheetName": null, "Series": [ { "Data": [ { "DateFrom": "2022-10-01T00:00:00+02:00", ... and so on ...
You should see the sensors update as usual.
If all of this works, you know the docker container is running and the service can be accessed from Home Assistant.
This is the second test, now using the real endpoint. If you do this many times over in a short timeframe you may get tagged as a robot and will need to login manually and wait for some hours.
5900
.coordinator.py
file to use the novafos-token
endpoint.If this works, let it run and be happy.
!Note! Data is delayed in the data warehouse. Data validity will range from 24h to 5 days ago from today's midnight. This means the sensor data represents historical data.
The integration creates the following sensors:
All water sensors show their value in cubic meters (m3). The sensors also have extended attributes as outlined above, which can be used by ex. apexchart-card to chart data at the correct date. You can also create new sensors from these attributes to save them in the history database. Attributes are not saved in the history.
It is possible to debug log the raw response from KMD API. This is done by setting up logging like below in configuration.yaml in Home Assistant. It is also possible to set the log level through a service call in UI. Be aware that a lot of information is dumped to the log, so only have this activated when reporting a bug.
logger:
default: info
logs:
custom_components.novafos: debug
This example is just an entity card with the latest data of all sensors. It shows when the latest data was valid as a reference.
This is a configuratio for the apexchart card. Because data retrieved today may be at least 24 hours old, graphing the sensor state will put values on the wrong date. If this is not wanted, the sensors also provide attributes with the data and the correct dates. Apexchart can graph this.
TBD: One caveat though is that attributes are not saved in the sensor history. So what the module does is to fetch daily use from the start of the month, and hourly data 7 days back or so. Then from the attributes it is at least possible to put daily and hourly use at the correct date.
The sensors still save daily and hourly values but remember these values are only as valid as the latest data available from the API.
type: custom:apexcharts-card
graph_span: 7d
span:
end: day
offset: '-1d'
header:
show: true
title: Water year to date
show_states: true
colorize_states: true
yaxis:
- id: left
decimals: 3
- id: right
opposite: true
decimals: 2
series:
- entity: sensor.novafos_day_total
extend_to_end: false
type: column
yaxis_id: left
data_generator: |
return entity.attributes.data.map((start, index) => {
return [new Date(start["DateTo"]).getTime(), entity.attributes.data[index]["Value"]];
});
- entity: sensor.novafos_hour
extend_to_end: false
yaxis_id: left
type: column
data_generator: |
return entity.attributes.data.map((start, index) => {
return [new Date(start["DateTo"]).getTime(), entity.attributes.data[index]["Value"]];
});
- entity: sensor.novafos_year_total
type: column
yaxis_id: right
data_generator: >
return [[new Date(entity.attributes.last_valid_date).getTime(),
entity.state]]
- entity: sensor.novafos_month_total
type: column
yaxis_id: right
data_generator: >
return [[new Date(entity.attributes.last_valid_date).getTime(),
entity.attributes.data[0]["Value"]]]