I was wondering if and wen Hozelock Will be a supported censor. I have a cloud controller kit and would like to intergratie this. Maybe anyone any tips.
How are you doing with this? I have also just ordered one and am also wanting to integrate into HA.
I automated my Hozelock Cloud Controller with shell scripts which call the (undocumented) cloud API (reverse-engineered from looking at requests made by the android app), I didn’t look at local (ie no cloud dependency) control.
The device has pretty much 0 security, requests to the API have no authentication, and just identify each device by its unique device ID. I raised this issue with Hozelock, and proved it to them by remotely activating a device in their office, but they weren’t at all interested. (never followed up or made any changes to it)
There’s a basic bash script below for turning the controller on/off, the API endpy to start/stop is waterNow/stopWatering. iirc you should be able to play with the API to find all available endpoints
For status & feedback you can make a GET request to
http://hoz3.com/restful/support/hubs/HUBID/, which returns status as JSON.
ACTION=$1
DURATION=$2
PAYLOAD='{"controllerIDs":["0","0"],"duration":'${DURATION}'}'
curl -X POST "http://hoz3.com/restful/foo/hubs/${HUBID}/controllers/actions/${ACTION}" -H 'content-type: application/json' -d $PAYLOAD > /dev/null 2>&1```
Good Stuff.
Shame it is so open, you would almost want to network isolate that hub and just address and control it locally form HA. Thanks for that data, will see how it works when it finally gets delivered.
On a side note, when would you like me to water your garden?
Assuming that all of the 6 character hub ID’s follow the LNLLNL format, then there are only 45,697,600 possible ID’s.
There’s also no API rate-limiting on their server, so polling it (annoyingly with a GET as it doesn’t respond to HEAD requests) to see which ID’s respond would give you a complete list of all live hubs.
There I was wanting to just water our gardens, but you want to water the world! How benevolent.
Not a home-assist user my self, however my hubs number/Letter format is LNNNLN.
There may be up to 10,314,424,798,490,500,000,000,000,000 combinations on the basis of 6^36, of course in reality a lot of combinations won’t exist such as all numbers or those less than 6 digits.
Regards: eveares.
Thanks to @anthonyangel I wrote up everything I learnt about the Hozelock API and included more information form what he shared.
I was going to post it here but it got … long.
Hope it is helpful to some of you.
Thanks - interesting read.
Personally I think it’s absolutely shocking that there is no forced TLS or any auth at all on their API.
Especially since @anthonyangel took the time to demonstrate that he could control their device.
Its extremely irresponsible.
Has anyone found out how the traffic is between the hub and the server? Is it possible to create your own server?
Cheers
Here’s a config code for sensors. I recon it could be done better using binary_sensor for some of the variables.
Im still working on sending commands to the controller.
[updated version - 29.07.2019]
sensors:
- platform: rest
resource: !secret hozelock_controller_0
name: "Hozelock Back Garden Sprinkler"
value_template: '{{ value_json["controller"]["name"] }}'
json_attributes:
- controller
- platform: template
sensors:
hozelock_back_garden_sprinkler_pause_starttime:
friendly_name: "Pause start"
value_template: '{{ ( state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["pause"]["startTime"] | int / 1000 ) | int | timestamp_local }}'
hozelock_back_garden_sprinkler_pause_endtime:
friendly_name: "Pause end"
value_template: '{{ ( state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["pause"]["endTime"] | int / 1000 ) | int | timestamp_local }}'
hozelock_back_garden_sprinkler_pause_duration:
friendly_name: "Pause duration"
value_template: '{{ ( state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["pause"]["duration"] | int / 60000 ) | int }}'
hozelock_back_garden_sprinkler_adjustment_starttime:
friendly_name: "Adjustment start"
value_template: '{{ ( state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["adjustment"]["startTime"] | int / 1000 ) | int | timestamp_local }}'
hozelock_back_garden_sprinkler_adjustment_endtime:
friendly_name: "Adjustment end"
value_template: '{{ ( state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["adjustment"]["endTime"] | int / 1000 ) | int | timestamp_local }}'
hozelock_back_garden_sprinkler_adjustment_wateringadjustment:
friendly_name: "Adjustment amount"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["adjustment"]["wateringAdjustment"] }}'
unit_of_measurement: '%'
hozelock_back_garden_sprinkler_waternowevent:
friendly_name: "Water now event"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["waterNowEvent"] }}'
hozelock_back_garden_sprinkler_currentwateringevent:
friendly_name: "Current watering event"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["currentWateringEvent"] }}'
hozelock_back_garden_sprinkler_nextwateringevent_starttime:
friendly_name: "Next watering start"
value_template: '{{ ( state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["nextWateringEvent"]["startTime"] | int / 1000 ) | int | timestamp_local }}'
hozelock_back_garden_sprinkler_nextwateringevent_endtime:
friendly_name: "Next watering end"
value_template: '{{ ( state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["nextWateringEvent"]["endTime"] | int / 1000 ) | int | timestamp_local }}'
hozelock_back_garden_sprinkler_nextwateringevent_duration:
friendly_name: "Next watering duration"
value_template: '{{ ( state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["nextWateringEvent"]["duration"] | int / 60000 ) | int}}'
unit_of_measurement: 'min'
hozelock_back_garden_sprinkler_lastcommunicationwithserver:
friendly_name: "Last communication"
value_template: '{{ ( state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["lastCommunicationWithServer"] | int / 1000 ) | int | timestamp_local }}'
hozelock_back_garden_sprinkler_nextcommunicationwithserver:
friendly_name: "Next communication"
value_template: '{{ ( state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["nextCommunicationWithServer"] | int / 1000 ) | int | timestamp_local }}'
hozelock_back_garden_sprinkler_batterystatus:
friendly_name: "Battery status"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["batteryStatus"] }}'
hozelock_back_garden_sprinkler_signalstrength:
friendly_name: "Signal strength"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["signalStrength"] }}'
hozelock_back_garden_sprinkler_overridescheduleduration:
friendly_name: "Override schedule duration"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["overrideScheduleDuration"] }}'
binary_sensors:
- platform: template
sensors:
hozelock_back_garden_sprinkler_haswaternowevent:
friendly_name: "Water now event"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["hasWaterNowEvent"] }}'
hozelock_back_garden_sprinkler_ischildlockenabled:
friendly_name: "Child lock"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["isChildlockEnabled"] }}'
hozelock_back_garden_sprinkler_iswatering:
friendly_name: "Watering now"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["isWatering"] }}'
hozelock_back_garden_sprinkler_ispanelremoved:
friendly_name: "Panel removed"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["isPanelRemoved"] }}'
hozelock_back_garden_sprinkler_isadjusted:
friendly_name: "Adjustment"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["isAdjusted"] }}'
hozelock_back_garden_sprinkler_isscheduleuptodate:
friendly_name: "Schedule up-to-date"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["isScheduleUpToDate"] }}'
hozelock_back_garden_sprinkler_ispaused:
friendly_name: "Paused"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["isPaused"] }}'
hozelock_back_garden_sprinkler_nextwateringevent_enabled:
friendly_name: "Next watering enabled"
value_template: '{{ state_attr("sensor.hozelock_back_garden_sprinkler", "controller")["nextWateringEvent"]["enabled"] }}'
And here’s a logic for rest_commands, please note, i havent tested all functions yet but they should work
rest_command:
hozelock_waternow:
url: 'https://hoz3.com/restful/support/hubs/{{ hub_id }}/controllers/actions/waterNow'
method: POST
payload: '{"controllerIDs":[{{ controller_id }}],"duration":{{ duration }}}'
content_type: 'application/json'
hozelock_pause:
url: 'https://hoz3.com/restful/support/hubs/{{ hub_id }}/controllers/actions/pause'
method: POST
payload: '{"controllerIDs":[{{ controller_id }}],"duration":{{ duration }}}'
content_type: 'application/json'
hozelock_unpause:
url: 'https://hoz3.com/restful/support/hubs/{{ hub_id }}/controllers/actions/unpause'
method: POST
payload: '{"controllerIDs":[{{ controller_id }}]}'
content_type: 'application/json'
hozelock_adjust:
url: 'https://hoz3.com/restful/support/hubs/{{ hub_id }}/controllers/actions/adjust'
method: POST
payload: '{"controllerIDs":[{{ controler_id }}],"duration":{{ duration }},"wateringAdjustment":{{ percentage }}}'
content_type: 'application/json'
hozelock_unadjust:
url: 'https://hoz3.com/restful/support/hubs/{{ hub_id }}/controllers/actions/unadjust'
method: POST
payload: '{"controllerIDs":[{{ controller_id }}]}'
content_type: 'application/json'
hozelock_stopwatering:
url: 'https://hoz3.com/restful/support/hubs/{{ hub_id }}/controllers/actions/stopWatering'
method: POST
payload: '{"controllerIDs":[{{ controller_id }}]}'
content_type: 'application/json'
Hi @dinth
Can you explain how your code works because I tried it but everything is unknown (I can see the json values in my web browser when I go to http://hoz3.com/restful/support/hubs/xxxxxx)
@martynjsimpson
How can we use your API in home assistant?
There’s not much code above, just some sensor templates.
Are you getting any warnings in the log? Does the config validates in your HA?
Is the rest sensor unknown too?
I understand that everything depends on the rest sensor, but i get an unknown state. I’ve got no warnings in the log and the config validates in HA.
Do I need to change soething besides hozelock_controller_0 value ?
Can you explain value_template and json_attributes of the rest sensor ?
OK, got it: I was using http://hoz3.com/restful/support/hubs/xxxxxx for hozelock_conyroller_0 value but apparently we must use http://hoz3.com/restful/support/hubs/xxxxxx/controllers/0 instead. It was not obvious in your post
Hi, could you make a clumsy guide?
I’m starting with the house assistant and it’s hard for me to follow the steps.
I would appreciate it very much and surely more people like me too.
- add in your configuration.yaml file a section with Michal’s sensors code
- add in your secrets.yaml file this:
hozelock_controller_0: https://hoz3.com/restful/support/hubs/XXXXX/controllers/0
replace XXXXX with your hub ID
Tell me if you want also to send commands, I will show you how I do it with the waternow command
thanks for answering.
I have copied Michal´s sensors code
- platform: rest + platform: template sensors + binary_sensors
I have also copied everything in rest_command:
I have copied all this in configuration.yaml
then create secrets.yaml and copy the line
it is right ?
YOU should tell me if it’s right by clicking on Check config (left menu/Configuration/Server control) before restarting Home assistant and by testing
If you want to use the commands hozelock_waternow, hozelock_stopwatering, hozelock_pause and hozelock_unpause, you must add:
- in configuration.yaml:
input_number:
hozelock_duration:
name: Duration
min: 1
max: 60
step: 1
icon: mdi:clock-outline
unit_of_measurement: "min"
hozelock_duration_pause:
name: Duration
min: 1
max: 14
step: 1
icon: mdi:clock-outline
unit_of_measurement: "days"
- in scripts.yaml:
hozelock_waternow:
alias: Hozelock water now
sequence:
- service: rest_command.hozelock_waternow
data_template:
hub_id: !secret hozelock_hub_id
controller_id: 0
duration: "{{ states('input_number.hozelock_duration') | int * 60000 }}"
hozelock_stopwatering:
alias: Hozelock stop watering
sequence:
- service: rest_command.hozelock_waternow
data_template:
hub_id: !secret hozelock_hub_id
controller_id: 0
hozelock_pause:
alias: Hozelock pause
sequence:
- service: rest_command.hozelock_pause
data_template:
hub_id: !secret hozelock_hub_id
controller_id: 0
duration: "{{ states('input_number.hozelock_duration_pause') }}"
hozelock_unpause:
alias: Hozelock unpause
sequence:
- service: rest_command.hozelock_unpause
data_template:
hub_id: !secret hozelock_hub_id
controller_id: 0
- in secrets.yaml:
hozelock_hub_id: XXXXXX
replace XXXXXX with your hub id
I don’t use the others commands for now
Use the scripts to run the commands