Hulptroepen
TimWeFabricate opened this issue · 16 comments
Hi there zeekoe,
A Weheat dev here, you can login into the API using any https client / OpenIdDict. You'll need to access api.weheat.nl for our api and auth.weheat.nl to access the OAuth2 login.
You need to use a client login first to be able to login as a user. I have setup a community API with client id "WeheatCommunityAPI". You should be able to specify any redirect-uri and open a login screen in your browser on auth.weheat.nl redirecting to your own client.
I am pleased to see your efforts to implement an API. However please mindful to not spam our server and limit the rate. Our system is brand new and the bottlenecks are currently still being researched so it is fragile.
I haven't made an API without a password yet but you should be able to use: the following link to get an accesstoken to be able to use the WebAPI:
auth.weheat.nl/auth/realms/weheat/protocol/openid-connect/token/grant_type=password&client_id={clientId}&username={username}&password={password}&scope=openid
(encoding UTF8, mediatype application/x-www-form-urlencoded).
with clientid = WeheatCommunityAPI, username = your email for login and password = your password for login.
This should allow you to get an accesstoken so any https client with that token (in header as a JWT bearer) can use api.weheat.nl
I do use that link for clients that are password protected, so you might need to tweak it for that to work (like a different grant_type or something).
Hi Tim,
Thanks a lot, that is very helpful!
For sure I'll take care of not spamming your servers. Currently I take the latest heat pump log by day every 15 seconds, by night every 30 seconds. Would that be OK if more people start using it?
I can imagine it would also help: currently all graph data seems to be retrieved 'live' with some waiting time. If I can get graphs out of Grafana again, that would save some load on the server. :)
I tried a few things with variations on your URL and didn't get it to work yet, but I get clear error messages. Will get there, thanks again!
And don't hesitate to contact me if I'm doing stuff that's not OK. Not sure how I can get my contact details to you, but perhaps you already have made the connection. :)
- edit - or just open an issue here indeed, that will work well :)
Thanx @TimWeFabricate , If I am right this is the way to go forward:
curl -X POST https://auth.weheat.nl/auth/realms/Weheat/protocol/openid-connect/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Accept: application/json' \
-d 'grant_type=password' \
-d 'client_id=WeheatCommunityAPI' \
-d 'scope=openid' \
-d 'username=XXXXX' \
-d 'password=YYYYY'
You get back
{
"access_token": "XXXX"
}
Then you call
curl https://api.weheat.nl/api/v1/heat-pumps/${heatPumpId}/logs \
-H 'Authorization: Bearer ${access_token}' \
-H 'Content-Type: application/json'
Correct?
I do not have a login yet.
Thanks @NetEvolutions for your help too. I got it working! Got my first heat pump log in the new style. I'm hoping to have time to polish it enough today for pushing to github.
WeHeat currently provides a password grant type, but that is considered a legacy way of authentication. It has disadvantages, see https://www.keycloak.org/docs/23.0.2/securing_apps/#_resource_owner_password_credentials_flow
Your app will probably run unattended in the background, and therefore it needs (in future) a form of machine to machine (m2m) authentication. Your app would need to be able to request a new access token on expiration, based on some refresh token that you store. So either https://www.keycloak.org/docs/23.0.2/securing_apps/#device-authorization-grant or https://www.keycloak.org/docs/23.0.2/securing_apps/#authorization-code
@TimWeFabricate is it possible to use one of the other grant types (in future)?
It's working again, code pushed to github. Thanks again :)
I believed the ClientId provides a way to get the client token and do the M2M connection (in this case without the password). You will need to open up a user login after anyway to be able to access your data. I will read up on that though as I thought you are now able to use a different link to refresh the token.
For getting the data I would just get the missing logs in intervals at startup so you don't need to keep your application running at all times (which you could also use Minute interval averages for to speed up that process as raw logs and be able to get all logs per minute for up to 2 days at a time). Just getting the latest every 15 sec will also not give you all of them. So getting the raw logs live I would do a request every minute for all logs in the last minute for a specific heat pump.
This way you'll have a 'live' feed of the data.
Thanks for the pointer!
I prefer to have recent values immediately over having very precise data, knowing that I wouldn't get all of the logs.
However, now I introduced the 'gapfiller', that fills the gaps every ~10 minutes, and an initial load of 2 hours. Please let me know if this stresses the servers too much and if there's a better way to get live and precise data.
The time window of ~10 minutes is purposely not exactly 10 minutes (to spread the load) and configurable.
BTW, the t1 and t2 returned from this second endpoint seems different from the /latest (null vs some values), is that on purpose?
Yes, they will be null for hybrid heat pumps. They are the sensors for the domestic hot water tank, which are only present in All-Electric setups.
Great, thanks!
For reference, I created a simple php api/proxy using this info: https://github.com/barryvdh/php-weheat-api-proxy
Few notes:
- You can use the refresh token instead of the passwords, after the first time. If you request
offline_access
scope, this token should not expire. Same endpoint as username/password, but grant_typerefresh_token
and instead of username/password, addrefresh_token
with the token. - You can get the current state with
/api/v1/heat-pumps/{heatpumpId}/logs/latest
which is a 5 second interval, but you should probably best not query that every second.
Question:
Is it possible to get the power usage? cmMassPowerIn
and cmMassPowerOut
are the power usages? What does that mean for the intervals? Is that average based on the the interval (eg 1 hour) or on the timeCoveredInInterval
property? Because that does not seem to match 1 hour exactly? And it only counts for the time it is heating, not for standby?
Example: Interval 1 year, starting this year.
timeCoveredInInterval: 368085
cmMassPowerInAverage": 595.3725052632952
Or is there another way to get the yearly/daily/overall usage?
I guess you're just requesting all the logs and adding those times, right? I guess I could retrieve the logs every X time, since the previous interval en sum cmMassPowerIn and cmMassPowerOut I guess. Not sure if that's optimal though.
@barryvdh nice. :)
cmMassPowerIn
is the power usage of the compressor (so exluding the fan and the PCB power usage), cmMassPowerOut
is the power delivered to the system (as accurately calculated as possible).
For the /latest
api, both are instantaneous values. I log everything to influxDB and then use a query like this:
SELECT integral("mean_in",1h)/1000 as Pin, integral("mean_out",1h)/1000 as Pout FROM ( SELECT MEAN("cm_mass_power_out") AS mean_out, MEAN("cm_mass_power_in") AS mean_in FROM "blackbird" WHERE time > now() -1h GROUP BY time(1m) fill(0) ) WHERE time > now() -1h
to have a somewhat accurate mean integrated value over the last hour.
Hope that helps...
Thanks. I currently use the latest
entry to show the current state in Homeassistant. Don't need to have complex energy stuff (yet), bit kWh usage (and perhaps output and COP), so will see if I can just sum the in/out values and increase the total. Or just also fetch all entries.
Thanks!