Cleverspa Integration?

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)

Still a few small snags, but feel free to try and let me know.

If you get on ok with it Iā€™ll do some more tidying and get it on Hacs.

Just put the files onto Home Assistant and went to add it on the Integrations and I am just getting ā€œConfig flow could not be loadedā€ when trying to add it

Iā€™ve only tested against the current stable and dev branches of HA. (core-2021.8.8).

Feel free to open an issue on github with the logs (keeps this forum tidier too).

Thanks.

Updated and got it going. Ill post any issues to GitHub

Do have this black for the user part but it might be a theme thing

Untitled