I’ve recently got a Lay-Z-Spa (Bestway) Hot Tub with the wi-fi pump (egg).
https://www.lay-z-spa.co.uk/lay-z-spa-wifi-app
I’ve captured the traffic from the app to allow me to automate in home assistant.
Interestingly at the moment, their app is not working properly, so this home assistant setup works better than the official app !
If anyone wants to do the same, then this might be useful.
Please get in touch if you have any questions.
This is an example call to check if the pump is online.
- platform: rest
name: hottub_online
resource: "https://mobileapi.lay-z-spa.co.uk/v1/gizwits/is_online"
headers:
Content-Type: application/x-www-form-urlencoded
method: POST
payload: !secret hottub_api_did
value_template: "{{ value_json.data }}"
The secrets you will need are…
hottub_api_did: did=AAaAaAAAAAAaaaaAAA9A9b&api_token=a1a1a1a1a2a2a2a2a12a1a1a1a2a2a2a2
hottub_email_password: email=email%40domain.com&password=XXxxYYyy
The API DID and API Token are obtained by using:
- platform: rest
name: hottub_login
scan_interval: 172000
resource: "https://mobileapi.lay-z-spa.co.uk/v1/auth/login"
headers:
Content-Type: application/x-www-form-urlencoded
method: POST
payload: !secret hottub_email_password
value_template: "{{ value_json.data.api_token }}"
json_attribute_path: "$.devices[0]"
json_attributes:
- did
You can get all status information using…
- platform: rest
name: hottub_status
resource: "https://mobileapi.lay-z-spa.co.uk/v1/gizwits/status"
headers:
Content-Type: application/x-www-form-urlencoded
method: POST
payload: !secret hottub_api_did
value_template: "{{ value_json.data.attr.power }}"
json_attributes_path: "$.data.attr"
json_attributes:
- system_err2
- wave_appm_min
- heat_timer_min
- heat_power
- earth
- wave_timer_min
- system_err6
- system_err7
- system_err4
- system_err5
- heat_temp_reach
- system_err3
- system_err1
- system_err8
- system_err9
- filter_timer_min
- heat_appm_min
- power
- temp_set_unit
- filter_appm_min
- temp_now
- wave_power
- locked
- filter_power
- temp_set
I’ve created template sensors…
- platform: template
sensors:
hottub_pump_temp:
availability_template: "{{ states('sensor.hottub_online') }}"
friendly_name: "HotTub Pump Temperature"
unit_of_measurement: '°C'
value_template: "{{ state_attr('sensor.hottub_status', 'temp_now') | int }}"
hottub_water_temp:
availability_template: "{{ states('sensor.hottub_online') }}"
friendly_name: "HotTub Water Temperature"
unit_of_measurement: '°C'
value_template: "{{ states('input_number.hottub_water_temp') | int }}"
hottub_pump_target:
availability_template: "{{ states('sensor.hottub_online') }}"
friendly_name: "HotTub Pump Target"
unit_of_measurement: '°C'
value_template: "{{ state_attr('sensor.hottub_status', 'temp_set') | int }}"
hottub_summary:
availability_template: "{{ states('sensor.hottub_online') }}"
friendly_name: "HotTub Status"
value_template: "{% if states('sensor.hottub_online') == 'false' %}offline{% elif states('input_boolean.hottub_scheduled') == 'on' and states('switch.hottub_filter') == 'off' %}scheduled{% elif states('switch.hottub_power') == 'off' %}off{% elif states('input_boolean.hottub_scheduled')=='on' %}scheduled{% elif states('switch.hottub_filter')=='off' %}on{% elif states('switch.hottub_heat')=='off'%}filter{% elif state_attr('sensor.huttub_status','heat_temp_reach')=='1' %}reached{% elif states('switch.hottub_bubbles')=='off' %}heat{% else %}bubbles{% endif %}"
some commands…
rest_command:
hottub_command:
method: POST
content_type: "application/x-www-form-urlencoded"
url: "https://mobileapi.lay-z-spa.co.uk/v1/gizwits/{{hottub_command}}"
payload: !secret hottub_api_did
hottub_temp_set:
method: POST
content_type: "application/x-www-form-urlencoded"
url: "https://mobileapi.lay-z-spa.co.uk/v1/gizwits/temp_set"
payload: "&{{hottub_api_did}}&temperature={{ states('input_number.hottub_water_target') | int }}"
hottub_temp_set_unit:
method: POST
content_type: "application/x-www-form-urlencoded"
url: "https://mobileapi.lay-z-spa.co.uk/v1/gizwits/temp_set_unit"
payload: "{{hottub_api_did}}&unit={{hottub_tempcode}}"
# on for 3 hours, off for 4 at 36
# 0, 0, 0 for cancel schedule
hottub_set_schedule:
method: POST
content_type: "application/x-www-form-urlencoded"
url: "https://mobileapi.lay-z-spa.co.uk/v1/gizwits/set_schedule"
payload: "{{ hottub_api_did }}&heat_in={{ hottub_heat_in | int | string }}&duration={{ hottub_duration | int | string }}&temperature={{ hottub_temp | int | string }}"
and some switches…
switch:
- platform: template
switches:
hottub_power:
availability_template: "{{ states('sensor.hottub_online') }}"
friendly_name: Power
unique_id: hottub_power
value_template: "{% if state_attr('sensor.hottub_status', 'power') == 1 %}on{% else %}off{% endif %}"
turn_on:
- service: rest_command.hottub_command
data:
hottub_command: turn_on
- delay: 00:00:05
- service: homeassistant.update_entity
entity_id: sensor.hottub_status
turn_off:
- service: rest_command.hottub_command
data:
hottub_command: turn_off
- delay: 00:00:05
- service: homeassistant.update_entity
entity_id: sensor.hottub_status
hottub_filter:
availability_template: "{{ states('sensor.hottub_online') }}"
unique_id: hottub_filter
friendly_name: Filter
value_template: "{% if state_attr('sensor.hottub_status', 'filter_power') == 1 %}on{% else %}off{% endif %}"
turn_on:
- service: rest_command.hottub_command
data:
hottub_command: turn_filter_on
- delay: 00:00:05
- service: homeassistant.update_entity
entity_id: sensor.hottub_status
turn_off:
- service: rest_command.hottub_command
data:
hottub_command: turn_filter_off
- delay: 00:00:05
- service: homeassistant.update_entity
entity_id: sensor.hottub_status
hottub_heat:
availability_template: "{{ states('sensor.hottub_online') }}"
unique_id: Heater
friendly_name: Heater
value_template: "{% if state_attr('sensor.hottub_status', 'heat_power') == 1 %}on{% else %}off{% endif %}"
turn_on:
- service: rest_command.hottub_command
data:
hottub_command: turn_heat_on
- delay: 00:00:05
- service: homeassistant.update_entity
entity_id: sensor.hottub_status
turn_off:
- service: rest_command.hottub_command
data:
hottub_command: turn_heat_off
- delay: 00:00:05
- service: homeassistant.update_entity
entity_id: sensor.hottub_status
hottub_bubbles:
availability_template: "{{ states('sensor.hottub_online') }}"
unique_id: hottub_bubbles
friendly_name: Bubbles
value_template: "{% if state_attr('sensor.hottub_status', 'wave_power') == 1 %}on{% else %}off{% endif %}"
turn_on:
- service: rest_command.hottub_command
data:
hottub_command: turn_wave_on
- delay: 00:00:05
- service: homeassistant.update_entity
entity_id: sensor.hottub_status
turn_off:
- service: rest_command.hottub_command
data:
hottub_command: turn_wave_off
- delay: 00:00:05
- service: homeassistant.update_entity
entity_id: sensor.hottub_status
Finally some automations to turn on the pump and log the water temperature periodically and to allow target temp to be captured and updated…
automation:
- alias: Set Hot Tub Temp
mode: restart
trigger:
- platform: state
entity_id: sensor.hottub_pump_temp
- platform: time_pattern
minutes: '/15'
condition:
- condition: state
entity_id: 'switch.hottub_filter'
state: 'on'
- condition: numeric_state
entity_id: 'sensor.hottub_pump_temp'
above: 20
action:
- delay: 00:01:00
- service: input_number.set_value
data:
entity_id: input_number.hottub_water_temp
value: "{{ states('sensor.hottub_pump_temp') | int }}"
- alias: Pump on five every 30
trigger:
- platform: time_pattern
minutes: '/30'
condition:
condition: state
entity_id: 'switch.hottub_filter'
state: 'off'
action:
- service: rest_command.hottub_command
data:
hottub_command: turn_filter_on
- delay: 00:05:00
- service: rest_command.hottub_command
data:
hottub_command: turn_off
- alias: Hot Tub Off At Peak
trigger:
- platform: state
entity_id: switch.hottub_heat
to: 'on'
- platform: time
at: "16:00:00"
condition:
- condition: state
entity_id: switch.hottub_heat
state: 'on'
- condition: time
after: '15:59:00'
before: '19:00:00'
action:
service: rest_command.hottub_command
data:
hottub_command: turn_off
- alias: Set Hot Tub Target
trigger:
platform: state
entity_id: sensor.hottub_pump_target
condition:
condition: numeric_state
entity_id: 'sensor.hottub_pump_target'
above: 20
action:
service: input_number.set_value
data_template:
entity_id: input_number.hottub_water_target
value: "{{ states('sensor.hottub_pump_target') | int }}"
- alias: Change Hot Tub Target
trigger:
platform: state
entity_id: input_number.hottub_water_target
action:
- service: rest_command.hottub_temp_set
data:
hottub_api_did: !secret hottub_api_did
Next is to use an automation to ensure that the tub is at target temperature by a particular time whilst not heating during peak electric pricing (4 till 7pm - Octopus Agile).
Thanks for reading.