Jacuzzi - Arctic Spas API

Arctic Spas API
Hi, I’ve received early access to the Arctic Spas API.
I have minimal experience with both APIs and Home Assistant, but I’m learning as I go. And I think I’ve jumped to the deep end with this one, at least it feels like it.

I’ve managed to create sensors, not sure if it’s perfect, but now I’m trying to make a switch and it’s kind of difficult to figure out how to do it.

Any suggestions, tips and tricks or any kind of help would be greatly appricated.

What I’ve managed to do so far:

sensor:
- platform: rest
  resource: https://api.myarcticspa.com/v2/spa/status
  headers: 
    X-API-KEY: !secret arctic_spa_apikey
    Content-Type: application/json
  method: GET
  name: "Arctic Spa Status"
  value_template: '{{ value_json.connected }}'
  json_attributes:
    - temperatureF
    - setpointF
    - lights
    - pump1
    - pump2
    - pump3
    - pump4
    - pump5
  scan_interval: 900
- platform: template
  sensors:
    arctic_spa_temperaturef:
      friendly_name: "Temperature F"
      value_template: "{{ state_attr('sensor.arctic_spa_status','temperatureF') }}"
- platform: template
  sensors:
    arctic_spa_setpointf:
      friendly_name: "Temperature F setpoint"
      value_template: "{{ state_attr('sensor.arctic_spa_status','setpointF') }}"
- platform: template
  sensors:
    arctic_spa_lights:
      friendly_name: "Lights"
      value_template: "{{ state_attr('sensor.arctic_spa_status','lights') }}"
- platform: template
  sensors:
    arctic_spa_pump1:
      friendly_name: "Pump 1"
      value_template: "{{ state_attr('sensor.arctic_spa_status','pump1') }}"
- platform: template
  sensors:
    arctic_spa_pump2:
      friendly_name: "Pump 2"
      value_template: "{{ state_attr('sensor.arctic_spa_status','pump2') }}"
- platform: template
  sensors:
    arctic_spa_pump3:
      friendly_name: "Pump 3"
      value_template: "{{ state_attr('sensor.arctic_spa_status','pump3') }}"
- platform: template
  sensors:
    arctic_spa_pump4:
      friendly_name: "Pump 4"
      value_template: "{{ state_attr('sensor.arctic_spa_status','pump4') }}"
- platform: template
  sensors:
    arctic_spa_pump5:
      friendly_name: "Pump 5"
      value_template: "{{ state_attr('sensor.arctic_spa_status','pump5') }}"
- platform: template
  sensors:
    arctic_spa_temperaturec:
      friendly_name: "Temperature"
      unit_of_measurement: '°C'
      value_template: >-
        {% set t = state_attr('sensor.arctic_spa_status','temperatureF') | float %}
        {{((t)-32)*0.5556| round(2)}}
- platform: template
  sensors:
    arctic_spa_temperature_setpoint_c:
      friendly_name: "Temperature setpoint"
      unit_of_measurement: '°C'
      value_template: >-
        {% set t = state_attr('sensor.arctic_spa_status','setpointF') | float %}
        {{((t)-32)*0.5556| round(2)}}

What I’m struggeling with is to create a switch for the lights.
I’ve looked at rest switches with resource and state_resource, I’v looked at the rest_command, but I can’t figure out how to get it to work.

You can see the APIs here: https://api.myarcticspa.com/

I can get the light status from the template sensor above or this API call

And I can turn on and off the lights with this API call.
image

Rather than using the rest sensor platform and a bunch of separate template sensors you can use the rest integration to get all your sensors from the one call to the resource and do the F → C conversion all in one go:

rest:
  - resource: https://api.myarcticspa.com/v2/spa/status
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    method: GET
    scan_interval: 60
    sensor:
      - name : "Spa Temperature"
        value_template: "{{ ( (value_json.temperatureF - 32) * 0.5556 )|round(1) }}"
        unit_of_measurement: "°C"
        device_class: temperature
      - name: "Spa Temperature Setpoint"
        value_template: "{{ ( (value_json.setpointF - 32) * 0.5556 )|round(1) }}"
        unit_of_measurement: '°C'
        device_class: temperature
    binary_sensor:
      - name: "Spa Status"
        value_template: "{{ value_json.connected }}"
        device_class: connectivity
      - name: "Spa Lights"
        value_template: "{{ value_json.lights|bool }}"
        device_class: power
      - name: "Spa Pump 1"
        value_template: "{{ value_json.pump1|bool }}"
        device_class: power
      - name: "Spa Pump 2"
        value_template: "{{ value_json.pump2|bool }}"
        device_class: power
      - name: "Spa Pump 3"
        value_template: "{{ value_json.pump3|bool }}"
        device_class: power
      - name: "Spa Pump 4"
        value_template: "{{ value_json.pump4|bool }}"
        device_class: power

As for the switches you will need a rest command to turn each switch on, and another rest command to turn each switch off. You can then create a template switch from these commands and your sensors.

e.g. for the lights:

rest_command:
  spa_lights_on:
    url: "https://api.myarcticspa.com/v2/spa/lights"
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_ligfhts_off:
    url: "https://api.myarcticspa.com/v2/spa/lights"
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

Test these rest_commands in Developer Tools → Services. If they work then you can proceed to creating your switch:

switch:
  - platform: template
    switches:
      spa_lights:
        friendly_name: Spa Lights
        value_template: "{{ states('binary_sensor.spa_lights') }}"
        turn_on:
          - service: rest_command.spa_lights_on
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_lights # force the rest sensor to update rather than waiting for the scan interval
        turn_off:
          - service: rest_command.spa_lights_off
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_lights # force the rest sensor to update rather than waiting for the scan interval
        icon_template: >
          {% if is_state('binary_sensor.spa_lights', 'on') %}
            mdi:lightbulb-on
          {% else %}
            mdi:lightbulb-off
          {% endif %}

      spa_pump_1:
        friendly_name: Spa Pump 1
        ... repeat as above.
2 Likes

For setting the temperature set point create an input_number (in °C, we’ll convert it before sending):

spa_set_temperature:
  name: Spa Set Temperature
  min: 25
  max: 35 # or whatever the min and max are
  step: 0.1
  unit_of_measurement: "°C"
  icon: mdi:thermometer

Then create a rest command

rest_command:
  spa_set_temperature:
    url: "https://api.myarcticspa.com/v2/spa/temperature"
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"setpointF": (states("input_number.spa_set_temperature")|float(0) * 1.8) - 32 )|round(0)|int(0) }'

You will then need an automation to get (if changed outside HA) and set (if the input number is changed) the temperature:

- alias: 'Set Spa Temperature'
  trigger:
    - platform: state
      entity_id: input_number.spa_set_temperature
      to:
  condition:
    - condition: template
      value_template: "{{ trigger.to_state.state not in ['unknown', 'unavailable'] }}"
    - condition: template
      value_template: "{{ states('sensor.spa_temperature_setpoint')|float(30) != states('input_number.spa_set_temperature')|float(30) }}"
  action:
    - service: rest_command.spa_set_temperature

- alias: 'Get Spa Temperature'
  trigger:
  - platform: state
    entity_id: sensor.spa_temperature_setpoint
    to:
  condition:
    - condition: template
      value_template: "{{ trigger.to_state.state not in ['unknown', 'unavailable'] }}"
    - condition: template
      value_template: "{{ states('sensor.spa_temperature_setpoint')|float(30) != states('input_number.spa_set_temperature')|float(30) }}"
  action:
    - service: input_number.set_value
      data:
        entity_id: input_number.spa_set_temperature
        value: "{{ states('sensor.spa_temperature_setpoint')|float(30) }}"

Be very careful with the precision here. Epsilon errors may cause these two automations to loop forever. However I think by rounding to 1 decimal place in your Spa Temperature Setpoint sensor we should be ok. If it does loop forever we’ll have to use the format function as well as the round filter.

Alternatively you can do everything in °F and integers rather than °C floating point numbers.

1 Like

Thanks! I would never have figured out this on my own. I’ll try and find some time to play around with it this weekend.

I got the light switch to work and I’m working on the pump switches now. I got one issue, and that is the ‘on’ state of the pump return ‘high’ when the pump is running. I guess I need to convert ‘high’ to a boolean.
I was hoping this would work, but it’s not, any suggestions?

binary_sensor:
  - name: "Spa Pump 1"
  value_template: "{% if is_state('value_json.pump1', 'high')  %}true{% else %}false{% endif %}"
  device_class: power

image

EDIT:

I figured it out. This will return true or false.

binary_sensor:
  - name: "Spa Pump 1"
  value_template: "{{ value_json.pump1 == 'high' }}"
2 Likes

Doe it have more than two states?

e.g.

high
med
low
off

Pump1 has three states. off,low and high. The other pumps only have high and off.

It should be a sensor then. Not a binary_sensor.

For the switch for it you have a couple of options.

  1. use two switches, one for high, one for low, or…
  2. Use an input_select with the three options off, low, high and then automate which rest command is sent based on the state of this input select.

Thanks, I’ll see how the input_select works and decide. The low state is mostly used by the tub to heat the water.
I might need it when they expand the api with energy data and PH level.

I tried to change the payload string,but when I paste it in the configuration it looks like it’s not properly formated.

payload: '{"setpointF": "{{ (states('input_number.spa_set_temperature')|float(0)* 1.8 +32|round(0))|int(0)}}" }'

When I paste it in it looks like this:

I think I got most of the configuration now except the set temperature.

configuration.yaml

rest:
  - resource: https://api.myarcticspa.com/v2/spa/status
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    method: GET
    scan_interval: 60
    sensor:
      - name : "Spa Temperature"
        value_template: "{{ ((value_json.setpointF -32)|float(0) * 0.5556)|round(0)|int(0) }}"
        unit_of_measurement: "°C"
        device_class: temperature
      - name: "Spa Temperature Setpoint"
        value_template: "{{ ((value_json.setpointF -32)|float(0) * 0.5556)|round(0)|int(0) }}"
        unit_of_measurement: '°C'
        device_class: temperature
    binary_sensor:
      - name: "Spa Status"
        value_template: "{{ value_json.connected }}"
        device_class: connectivity
      - name: "Spa Lights"
        value_template: "{{ value_json.lights|bool }}"
        device_class: power
      - name: "Spa Pump 1 Low"
        value_template: "{{ value_json.pump1 == 'low' }}"
        device_class: power
      - name: "Spa Pump 1"
        value_template: "{{ value_json.pump1 == 'high' }}"
        device_class: power
      - name: "Spa Pump 2"
        value_template: "{{ value_json.pump2 == 'high' }}"
        device_class: power
      - name: "Spa Pump 3"
        value_template: "{{ value_json.pump3 == 'high' }}"
        device_class: power
      - name: "Spa Pump 4"
        value_template: "{{ value_json.pump4 == 'high' }}"
        device_class: power

rest_command:
  spa_lights_on:
    url: "https://api.myarcticspa.com/v2/spa/lights"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_lights_off:
    url: "https://api.myarcticspa.com/v2/spa/lights"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_pump_1_on:
    url: "https://api.myarcticspa.com/v2/spa/pumps/1"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_pump_1_low:
    url: "https://api.myarcticspa.com/v2/spa/pumps/1"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "low"}'

  spa_pump_1_off:
    url: "https://api.myarcticspa.com/v2/spa/pumps/1"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_pump_2_on:
    url: "https://api.myarcticspa.com/v2/spa/pumps/2"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_pump_2_off:
    url: "https://api.myarcticspa.com/v2/spa/pumps/2"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_pump_3_on:
    url: "https://api.myarcticspa.com/v2/spa/pumps/3"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_pump_3_off:
    url: "https://api.myarcticspa.com/v2/spa/pumps/3"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_pump_4_on:
    url: "https://api.myarcticspa.com/v2/spa/pumps/4"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_pump_4_off:
    url: "https://api.myarcticspa.com/v2/spa/pumps/4"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_set_temperature:
    url: "https://api.myarcticspa.com/v2/spa/temperature"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"setpointF": }'

switch:
  - platform: template
    switches:
      spa_lights:
        friendly_name: Spa Lights
        value_template: "{{ states('binary_sensor.spa_lights') }}"
        turn_on:
          - service: rest_command.spa_lights_on
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_lights # force the rest sensor to update rather than waiting for the scan interval
        turn_off:
          - service: rest_command.spa_lights_off
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_lights # force the rest sensor to update rather than waiting for the scan interval
        icon_template: >
          {% if is_state('binary_sensor.spa_lights', 'on') %}
            mdi:lightbulb-on
          {% else %}
            mdi:lightbulb-off
          {% endif %}
      spa_pump_1:
        friendly_name: Spa Pump 1
        value_template: "{{ states('binary_sensor.spa_pump_1') }}"
        turn_on:
          - service: rest_command.spa_pump_1_on
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_1 # force the rest sensor to update rather than waiting for the scan interval
        turn_off:
          - service: rest_command.spa_pump_1_off
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_1
        icon_template: >
          {% if is_state('binary_sensor.spa_pump_1', 'on') %}
            mdi:water
          {% else %}
            mdi:water-off
          {% endif %}
      spa_pump_1_low:
        friendly_name: Spa Pump 1 Low
        value_template: "{{ states('binary_sensor.spa_pump_1_low') }}"
        turn_on:
          - service: rest_command.spa_pump_1_low
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_1_low # force the rest sensor to update rather than waiting for the scan interval
        turn_off:
          - service: rest_command.spa_pump_1_off
          - delay: 2 # Larger delay because it goes to high before it turns off
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_1_low
        icon_template: >
          {% if is_state('binary_sensor.spa_pump_1', 'on') %}
            mdi:water
          {% else %}
            mdi:water-off
          {% endif %}
      spa_pump_2:
        friendly_name: Spa Pump 2
        value_template: "{{ states('binary_sensor.spa_pump_2') }}"
        turn_on:
          - service: rest_command.spa_pump_2_on
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_2 # force the rest sensor to update rather than waiting for the scan interval
        turn_off:
          - service: rest_command.spa_pump_2_off
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_2
        icon_template: >
          {% if is_state('binary_sensor.spa_pump_2', 'on') %}
            mdi:water
          {% else %}
            mdi:water-off
          {% endif %}
      spa_pump_3:
        friendly_name: Spa Pump 3
        value_template: "{{ states('binary_sensor.spa_pump_3') }}"
        turn_on:
          - service: rest_command.spa_pump_3_on
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_3 # force the rest sensor to update rather than waiting for the scan interval
        turn_off:
          - service: rest_command.spa_pump_3_off
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_3
        icon_template: >
          {% if is_state('binary_sensor.spa_pump_3', 'on') %}
            mdi:water
          {% else %}
            mdi:water-off
          {% endif %}
input_number:
  spa_set_temperature:
    name: Spa Set Temperature
    min: 15
    max: 40
    step: 0.5
    unit_of_measurement: "°C"
    icon: mdi:thermometer

Look at my example again. Yours has the parentheses in the wrong place and so you are only rounding the number 32.

I tried to use it but nothing is happening.I tried to modify your example from

payload: '{"setpointF": (states("input_number.spa_set_temperature")|float(0) * 1.8) - 32 )|round(0)|int(0) }'

to

payload: '{"setpointF": ((states("input_number.spa_set_temperature")|float(0) * 1.8) - 32 )|round(0)|int(0) }'

It seemed like it was missing a ( infront of states. Still does not work.

This is how it looks like when I paste it in the Template section under Dev Tools

payload: '{"setpointF": {{ (states("input_number.spa_set_temperature")|float(0) * 1.8 - 32 )|round(0)|int(0) }} }'
1 Like

YES! it works! :slight_smile: I just had to modified -32 to +32 to get the calculation right. Thank you for bearing with me!

  spa_set_temperature:
    url: "https://api.myarcticspa.com/v2/spa/temperature"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"setpointF": {{ (states("input_number.spa_set_temperature")|float(0) * 1.8 + 32 )|round(0)|int(0) }} }'
1 Like

Hey dagm,

I’m trying to get an apikey. How do I get it?

-g

Hi, it’s in early access at the moment so they will probably need to give you access.
Try this page and see if you can create one:

API Key Management (myarcticspa.com)

Hi,

I got " Error Page! Page doesn’t exist or some other error occured. Go to our home page or go back to [previous page](javascript:history.back())"

message.

Do I call and request one?

I’ll send you the email address to the guy that gave me access. I don’t want to post it online so I’ll send it by PM.

1 Like

Keen also - could you PM me the email please?

1 Like

Did you ever find out how to get your API key by chance?