Cleverspa Integration?

Has anyone has any luck or working on an integration for the Cleverspa Hot Tubs? Not sure how popular they are. They are WiFi enabled with an app.

Thanks

Assuming you have found this by now;

It is working pretty well.

Hey @pops106

Thanks for this. I’ll didn’t think about looking through the lay z spa one. I have looked through it all and seen the cleverspa stuff but don’t really know where to start to get it working… I assume I need mum did? Which I I am not good with API stuff.

Unless you have a basic step by step to help me? Maybe your yaml as well for sensors and buttons?

Sorry

Thanks again though

I did not manage to get my token. I seem to be having the same problem that you had here

With it creating another account so it says No Devices when I use the token. How did you find your Token ?

Thanks

It was a bit of a ball ache to be honest, I had to install some software on my PC and to do man in the middle inspection on my phone to get the details.

I think in the lazyspa post they have come up with an easier way, I will have a look and see if I can work out how to do it for cleverspa.

You could try this, just replace the email and password with the one you use on your cleverspa app.

Put this in your configuration.yaml and then restart home assistant and you should hopefully get a new sensor called hottub_login and under the attributes hopefully your DID

- platform: rest
    name: hottub_login
    scan_interval: 172000
    resource: "https://api.gizwits.com/app/login"
    headers:
      Content-Type: application/json
      X-Gizwits-Application-Id: "805cc6a3f41b48aeae471e2fcb6ebc73"
    method: POST
    payload: '{ "username": "[email protected]", "password": "xxxxxxxx", "lang": "en" }'    
    value_template: "{{ value_json.token }}"    
    json_attributes:
      - uid
      - expire_at

Another alternative which saves you messing with your home assistant might be to try this website

Then put this is in and click run

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'X-Gizwits-Application-Id: 805cc6a3f41b48aeae471e2fcb6ebc73' -d '{ "username": "xxxxxxxxx@xxxxxxxxx", "password": "xxxxxxxxx", "lang": "en" }' 'https://api.gizwits.com/app/login'

See if that gives you your DID

@pops106

I did try that curl website yesterday and got a token but I think it’s the same issue that you had which it just made a new account I think as I ran the command with the user address at the end… I used the same details for the account that I have on the cleverspa app.

Did you use fiddler as the man in the middle? As I didn’t have luck with seeing any commands go through that for details.

The HA login sensor just doesn’t show anything and the token I have just shows no devices when running the other curl command so I guess it thinks it’s another account

I used Mitm proxy

https://mitmproxy.org/

Couldn’t get fiddler to work, you sill need to install a certificate on your phone.

I think the cleverspa api is just a bit different to the lazy spa so the curl commands dont give what we need.

But mitm worked well

Did you not need a certificate for that program?

Now just got to try and work out how MIT works.

Did you use the yaml in the other post for the switches and sensors?

Thanks for your help again.

@pops106 Got my DID and Token using Mitmproxy :smiley: Thanks for that,

Now I am just trying to work out what all the sensors and automations that are needed as the switches dont update but the status does. I have just copied MusicMans yaml from this post and deleted the package from Bruces Github

Am I missing anything else to get it going?

Thanks

Nicely done, bit of messing around isn’t it.

This is what I have in my configuration.yaml

switch:
#Hottub
  - platform: template
    switches:
      hottub_heat:
        availability_template: "{{ states('binary_sensor.hottub_online') }}"
        unique_id: Heater
        friendly_name: Heater      
        value_template: "{% if state_attr('sensor.hottub_status', 'Heater') == 1 %}on{% else %}off{% endif %}"
        turn_on:
          - service: rest_command.hottub_command
            data_template: 
              hottub_command: >
                {"attrs": {"Heater": 1} }   
          - delay: 00:00:05
          - service: homeassistant.update_entity
            entity_id: sensor.hottub_status
        turn_off:
          - service: rest_command.hottub_command
            data_template: 
              hottub_command: >
                {"attrs": {"Heater": 0} }   
          - delay: 00:00:05
          - service: homeassistant.update_entity
            entity_id: sensor.hottub_status
      hottub_filter:
        availability_template: "{{ states('binary_sensor.hottub_online') }}"
        unique_id: hottub_filter
        friendly_name: Filter  
        value_template: "{% if state_attr('sensor.hottub_status', 'Filter') == 1 %}on{% else %}off{% endif %}"
        turn_on:
          - service: rest_command.hottub_command
            data_template: 
              hottub_command: >
                {"attrs": {"filter": 1} }   
          - delay: 00:00:05
          - service: homeassistant.update_entity
            entity_id: sensor.hottub_status
        turn_off:
          - service: rest_command.hottub_command
            data_template: 
              hottub_command: >
                {"attrs": {"filter": 0} }   
          - delay: 00:00:05
          - service: homeassistant.update_entity
            entity_id: sensor.hottub_status
      hottub_bubbles:
        availability_template: "{{ states('binary_sensor.hottub_online') }}"
        unique_id: Bubbles
        friendly_name: Bubbles      
        value_template: "{% if state_attr('sensor.hottub_status', 'Bubble') == 1 %}on{% else %}off{% endif %}"
        turn_on:
          - service: rest_command.hottub_command
            data_template: 
              hottub_command: >
                {"attrs": {"Bubble": 1} }   
          - delay: 00:00:05
          - service: homeassistant.update_entity
            entity_id: sensor.hottub_status
        turn_off:
          - service: rest_command.hottub_command
            data_template: 
              hottub_command: >
                {"attrs": {"Bubble": 0} }   
          - delay: 00:00:05
          - service: homeassistant.update_entity
            entity_id: sensor.hottub_status
#Rest Commands
rest_command:
  hottub_command: 
    method: POST
    headers:
      content_type: "application/json"
      X-Gizwits-Application-Id: "805cc6a3f41b48aeae471e2fcb6ebc73"
      X-Gizwits-User-token: "xxxxxxxxxxxxxxxxxxxx"
    url: "https://api.gizwits.com/app/control/xxxxxxxxxxxxxx"    
    payload: "{{hottub_command}}"
#Binary Sensors
binary_sensor:
  - platform: template
    sensors:
      hottub_online:
        friendly_name: "HotTub Online"
        value_template: "{{ (now() | as_timestamp - states('sensor.hottub_status') | as_timestamp ) < 2000.0 }}"
#Enable Sensors
sensor:
#Hottub
  - platform: rest
    name: hottub_status
    scan_interval: 60
    timeout: 30    
    resource: "https://api.gizwits.com/app/devdata/xxxxxxxxxxxxxxxxxxx/latest"  
    device_class: timestamp
    headers:
      Content-Type: application/json
      X-Gizwits-Application-Id: 805cc6a3f41b48aeae471e2fcb6ebc73
    method: GET
    value_template: "{{ value_json.updated_at | timestamp_custom ('%Y-%m-%dT%H:%M:%S+00:00') }}"
    json_attributes_path: "$.attr"
    json_attributes:
      - Heater
      - 03
      - Undercooling
      - Current_temperature
      - Filter
      - Temperature_setup
      - Superheat
      - Bubble
      - Overtime_filter
      - Timing
      - Check
      - Time_filter
  - platform: template
    sensors:
      hottub_pump_temp:
        availability_template: "{{ states('binary_sensor.hottub_online') }}"
        friendly_name: "HotTub Water Temperature"
        unit_of_measurement: '°C'
        value_template: "{{ state_attr('sensor.hottub_status', 'Current_temperature') | int }}"
      hottub_target_temp:
        availability_template: "{{ states('binary_sensor.hottub_online') }}"
        friendly_name: "HotTub Target Temperature"
        unit_of_measurement: '°C'        
        value_template: "{{ state_attr('sensor.hottub_status', 'Temperature_setup') | int }}"
      hottub_summary:
        availability_template: "{{ states('binary_sensor.hottub_online') }}"
        friendly_name: "HotTub Status"
        value_template: "{% if is_state('binary_sensor.hottub_online','off') %}offline{% elif is_state('sensor.hottub_error','on') %}error{% elif is_state('input_boolean.hottub_scheduled','on') and is_state('switch.hottub_filter','off') %}scheduled{% elif is_state('switch.hottub_power','off') %}off{% elif state_attr('sensor.hottub_status','heat_temp_reach')==1 %}at temperature{% elif is_state('switch.hottub_heat','on') %}heating{% elif is_state('switch.hottub_filter','off') %}on{% elif is_state('switch.hottub_heat','off') %}filtering{% elif is_state('switch.hottub_bubbles','off') %}heating{% else %}bubbling{% endif %}"
  - platform: history_stats
    name: HotTub Heating This Week
    entity_id: sensor.hottub_summary
    state: "heating"
    type: time
    end: "{{ now().replace(hour=0, minute=0, second=0) }}"
    duration:
      days: 7

@pops106

I will have a look at your configs when I am by the computer. This is what I have using musicmans. Shame I can’t work out how to update the input_number for the target temp when I change it in the app. It updates when I change it from HA with some of the automations from the original post just can’t get it the information the other way.

At least after so many months it’s finally in HA so I can set schedules as that’s what is really missing from the cleverspa app.

Awesome glad you got it sorted, my code is pretty much the same as musicmans, i used his as well.

I couldn’t work out the temp setting either but i use nodered for all my automations anyway so i just have it set it there for my peak and offpeak.

So 8:30pm offpeak sets tub to 42C and 1:30am sets it to 34C

Ah Ok, Yeah I noticed tonight that my input slider is updating when I change the temp in the app so it is working both ways now which is nice :smiley: Think the automations worked after I changed a few bits.

I started writing an integration for CleverSpa last night, uses CleverSpa’s Firebase config to get the auth token so the config flow simply asks for email and password and then stores just the token (since it seemingly doesn’t expire).

I went with water_heater entity type for the tub itself but actually this sucks to be honest as there’s no good lovelace cards as standard (despite climate being awfully close)

Will probably chuck it on Github in the coming days if others wish to test.

@Wh1terat

Very interested to try and test this if you would be willing to share it ? I know someone else on the lay z spa forum used it with the water integration part. I have managed to get the generic thermostat working with mine now. Just if you change the temp from the app home assistant will over ride the temp after a few seconds and reset it as I have automations.

If you can share it I’m sure it would help others as the Token and DID part are very annoying.

Sure no problem, just doing a little tidying up - will upload in the next day or so.

With regard to getting the auth token and did, extracted the relevant parts and just made a standalone gist:
https://gist.github.com/Wh1terat/71eaf8a43b1665e46a601cfb74a6ed6b

Sounds good! I look forward to trying it. I don’t know if you can get the setting the temperature going? That would be good to have.

Thanks again

Sure, setting temp works. It’s got full feature parity with the CleverLink app.

The underlying API is a little dumb, it will let you start the heater without the filter - doing this is not advised as I found out and will trigger an overheat warning.

I’ve covered this in my component, anytime you start / stop the heater it will also start / stop the filter in tandem.

Water heater entity really is unloved though. For example the step size is 0.5’c, despite setting precision to whole numbers. Climate has since gained ‘target_temperature_step’ but seemingly not made it’s way to water heater…

Ok, at least there is a form of setting the temp. I definitely will look forward to testing :blush: I got your python going yesterday for the did and token which was so much easier (wish we had that before)