Switch-Bot API integration

This works great, I’ve been able to work around the close button not working as expected by using a custom slider for the entity card (HACS), however when my curtains are closed it mention open in HA and when the curtains are open it mention close in HA. I’ve been searching however I’ve not been able to find a solution to set the cover positions in a cover template.

Thank you.

I have two curtains covering the same window. What is the process to link them as mentioned in step 2?

Is this via the app or changing the code in the cover ?

Has anyone been able to use to API to pull from a contact sensor in real time? i.e. instant (or near to) status updates when a door is open.

1 Like

They have updated the rate limit to 10000 last month

I will receive my curtains devices in a couple of weeks and will be looking to hook them up via the API seen some examples above but also have created custom components before, if it is not already out there i might look in to creating one for Switch-bot curtains.

Wonderfull to integrate the switchbot curtains via API. There a two things i could not solve:

  1. Anyone succeeded in creating an automation with de switchbot? Is it done by Service? Entity’s are not possible with automation (i would like to use the Sun Trigger!)
  2. I have two differtent windows with two bots. How to aggregate them in code?

For those of you struggling with one of the buttons for the curtains being greyed out: I solved it. It has to do with the slider position. In Home Assistant a slide position of 100 means fully opened and a slide position of 0 is fully closed. In the SwitchBot API it’s the exact opposite: a slide position of 100 is fully closed and 0 is fully opened. The trick is quite simple: subtract the SlidePosition value you get with the API from 100. You have to do the same with setting the position: subtract the value from the slider in HA from 100 and pass the result as a parameter to the SwitchBot API.

As I noticed that the curtains do not always report 0 or 100 if they have been fully opened or closed, but e.g. 1 or 99, I also fixed that, by using an if-statement in the sensor template. Furthermore, I left out the stop_cover command, because the API doesn’t support that.

I used the templates from @gdeboos. This is what the SwitchBot part of my configuration.yaml looks like after my modifications:

# Switchbot setup
rest_command:
  switchbot_device_command:
    url: 'https://api.switch-bot.com/v1.0/devices/{{ deviceId }}/commands'
    method: post
    content_type: 'application/json'
    headers:
      Authorization: !secret switchbot_api
    payload: '{"command": "{{ command }}","parameter": "{{ parameter }}"}'

sensor:
  - platform: rest
    name: 'Positie gordijnen balkon'
    resource: !secret switchbot_balkon_status_url
    method: GET
    scan_interval: 600
    headers:
      Authorization: !secret switchbot_api
      Content-Type: 'application/json'
    value_template: >
      {% if value_json.body.slidePosition > 95 %} 0
      {% elif value_json.body.slidePosition < 5 %} 100
      {% else %} {{100-value_json.body.slidePosition}}
      {% endif %}
    json_attributes_path: "$.body"
    json_attributes:
      - deviceId
      - deviceType
      - hubDeviceId
      - calibrate
      - group
      - moving
      - slidePosition

cover:
  - platform: template
    covers:
      gordijnen_balkon:
        device_class: curtain
        friendly_name: "Gordijnen balkon"
        unique_id: curtain.balkon
        position_template: "{{states('sensor.positie_gordijnen_balkon')}}"
        open_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_balkon_deviceId
            command: "turnOn"
        close_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_balkon_deviceId
            command: "turnOff"
        set_cover_position:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_balkon_deviceId
            command: "setPosition"
            parameter: "0,ff,{{100-position}}"


As you can see HA reports the position of the curtain for the balcony as 100 (fully opened), while the sensor read-out via the API for SlidePosition is 0.

7 Likes

image
Curtain fully opened, so slider position in HA at 100 (corresponding with a SwitchBot slide position of 0).

1 Like

image
Curtains partially open (70 percent open), so both arrow buttons can be clicked/tapped upon. BTW: up is open, down is close. :slight_smile:

1 Like

Does anyone have a template for the Color Bulb?
Please

2 Likes

Everything i try, the curtains won’t react to the commands in home assistant. Even when i open/close the curtains with the switchbot app, it is not displayed in the history in Home assistant.

Also the meter isn’t working
afbeelding

don’t know what i’m doing wrong. out of idea’s.

But what i see at your pictures looks great.

Hello. I didn’t find sample codes/ automations for the Switchbot humidifier in this thread. Here is my setup if anyone is interested. I have used some of the codes here to call API and for the automations, helpers and sensors, I used @ tom_l lounge heating and cooling automations.

Paste these codes and adjust to your HA environment. Best to restart HA since there are quite a few of codes. Hope I didn’t missed anything.

configuration.yaml

rest_command:
  switchbot_device_command:
    url: "https://api.switch-bot.com/v1.0/devices/{{ deviceId }}/commands"
    method: post
    content_type: "application/json"
    headers:
      Authorization: !secret switchbot_api
    payload: '{ "command": "{{ command }}", "parameter": "{{ parameter }}" }'

# humidifier sensors
rest:
  - resource: !secret switchbot_wohumi_waterlevel_url
    method: GET
    headers:
      Authorization: !secret switchbot_api
      Content-Type: 'application/json'
    scan_interval: 600 # adjust this to suite your need. There is api limit of 10,000 /per day.
    sensor:
      - name: SB Humidifier Lack Water
        value_template: "{{ value_json.body.lackWater }}"
        device_class: carbon_dioxide
      - name: SB Humidifier Nebulization Efficiency
        value_template: "{{ value_json.body.nebulizationEfficiency }}"
        device_class: ozone 
      - name: SB Humidifier Temperature
        value_template: "{{ value_json.body.temperature }}"
        device_class: temperature 
      - name: SB Humidifier Humidity
        value_template: "{{ value_json.body.humidity }}"
        device_class: humidity

secret.yaml

switchbot_api: '2ac4f4dxxxxxxxx6a0718ec'
switchbot_wohumi_waterlevel_url: 'https://api.switch-bot.com/v1.0/devices/<devicID>/status'
switchbot_wohumi_id: '<deviceID>'

input_select.yaml

  sb_humidifier_mode:
    name: SB Humidifier Mode
    icon: mdi:air-humidifier
    options:
      - 'Off'
      - Auto
      - Low
      - Med
      - High

input_number.yaml

  lrh_humidity_low_set:
    name: Humidity Low Set Point
    icon: mdi:thermometer
    initial: 30
    min: 0
    max: 100
    step: 1

  lrh_humidity_high_set:
    name: Humidity High Set Point
    icon: mdi:thermometer
    initial: 50
    min: 0
    max: 100
    step: 1

  lrh_humidity_intensity_set:
    name: Humidifier Intensity
    icon: mdi:water-plus
    min: 34
    max: 100
    step: 1

input_datetime.yaml

  lrh_ac_am_on_time:
    name: Humidifier AM On Time
    has_time: true
    initial: '05:00'
  lrh_ac_am_off_time:
    name: Humidifier AM Off Time
    has_time: true
    initial: '06:00'
  lrh_ac_pm_on_time:
    name: Humidifier PM On Time
    has_time: true
    initial: '18:30'
  lrh_ac_pm_off_time:
    name: Humidifier PM Off Time
    has_time: true
    initial: '19:00'

input_boolean.yaml

  lrh_humidifier_automation_enable:
    name: Humidifier Automation
    icon: mdi:av-timer
    initial: off

binary_sensor.yaml

      lrh_humidifier_am_automation_time_active:
        friendly_name: "LRH Humidifier AM Automation Time Active"
        value_template: >-
          {% set d = now().strftime("%Y-%m-%dT") %}
          {% set tz = as_timestamp(now()) | timestamp_custom('%z') %}
          {% set t = now().timestamp() %}
          {% set am_start = as_timestamp(d ~ states('input_datetime.lrh_ac_am_on_time') ~ tz) %}
          {% set am_end = as_timestamp(d ~ states('input_datetime.lrh_ac_am_off_time') ~ tz) %}
          {{ am_start <= t <= am_end }}

      lrh_humidifier_pm_automation_time_active:
        friendly_name: "LRH Humidifier PM Automation Time Active"
        value_template: >-
          {% set d = now().strftime("%Y-%m-%dT") %}
          {% set tz = as_timestamp(now()) | timestamp_custom('%z') %}
          {% set t = now().timestamp() %}
          {% set am_start = as_timestamp(d ~ states('input_datetime.lrh_ac_pm_on_time') ~ tz) %}
          {% set am_end = as_timestamp(d ~ states('input_datetime.lrh_ac_pm_off_time') ~ tz) %}
          {{ am_start <= t <= am_end }}

script.yaml

  humidifier_low:
    sequence:
      - service: rest_command.switchbot_device_command
        data:
          deviceId: !secret switchbot_wohumi_id
          command: 'setMode'
          parameter: 101
        
  humidifier_med:
    sequence:
      - service: rest_command.switchbot_device_command
        data:
          deviceId: !secret switchbot_wohumi_id
          command: 'setMode'
          parameter: 102

  humidifier_high:
    sequence:
      - service: rest_command.switchbot_device_command
        data:
          deviceId: !secret switchbot_wohumi_id
          command: 'setMode'
          parameter: 103

  humidifier_auto:
    sequence:
      - service: rest_command.switchbot_device_command
        data:
          deviceId: !secret switchbot_wohumi_id
          command: 'setMode'
          parameter: auto
          
  humidifier_off:
    sequence:
      - service: rest_command.switchbot_device_command
        data:
          deviceId: !secret switchbot_wohumi_id
          command: 'turnOff'
          parameter: default

  lrh_humidity_intensity_set:
    sequence:
      - service: rest_command.switchbot_device_command
        data:
          deviceId: !secret switchbot_wohumi_id
          command: 'setMode'
          parameter: "{{ states('input_number.lrh_humidity_intensity_set') }}"

automation.yaml

- alias: 'SB Humidifier'
  initial_state: true
  trigger:
    platform: state
    entity_id: input_select.sb_humidifier_mode
  action:
  - service_template: >
      {% if is_state('input_select.sb_humidifier_mode', 'Low') %} script.humidifier_low
      {% elif is_state('input_select.sb_humidifier_mode', 'Med') %} script.humidifier_med
      {% elif is_state('input_select.sb_humidifier_mode', 'High') %} script.humidifier_high
      {% elif is_state('input_select.sb_humidifier_mode', 'Auto') %} script.humidifier_auto
      {% elif is_state('input_select.sb_humidifier_mode', 'Off') %} script.humidifier_off
      {% endif %}


- alias: 'SB Humidifier Intensity'
  initial_state: true
  trigger:
    platform: state
    entity_id: input_number.lrh_humidity_intensity_set
  condition:
  - condition: template # Only if currently On
    value_template: "{{ is_state('input_boolean.sb_humidifier', 'on') }}"
  action:
  - service: script.lrh_humidity_intensity_set


- alias: 'SB Humidifier AM Schedule'
  trigger:
    - platform: state
      entity_id: binary_sensor.lrh_humidifier_am_automation_time_active
      to: 'on'
      for:
        seconds: 10
  condition:
    - condition: template # Only if automation is enabled
      value_template: "{{ is_state('input_boolean.lrh_humidifier_automation_enable', 'on') }}"
    - condition: template # Only if currently Off
      value_template: "{{ is_state('input_select.sb_humidifier_mode', 'Off') }}"
    - condition: numeric_state 
      entity_id: sensor.sb_humidifier_humidity
      above: input_number.lrh_humidity_low_set
      below: input_number.lrh_humidity_high_set
    - condition: template # Water tank not empty
      value_template: "{{ is_state('sensor.sb_humidifier_lack_water', 'False') }}"
    - condition: template # Someone is home
      value_template: "{{ is_state('input_select.home_mode', 'Home') }}"
  action:
    service: input_select.select_option
    data_template:
      entity_id: input_select.sb_humidifier_mode
      option: High


- alias: 'SB Humidifier PM Schedule'
  trigger:
    - platform: state
      entity_id: binary_sensor.lrh_humidifier_pm_automation_time_active
      to: 'on'
      for:
        seconds: 10      
  condition:
    - condition: template # Only if automation is enabled
      value_template: "{{ is_state('input_boolean.lrh_humidifier_automation_enable', 'on') }}"
    - condition: template # Only if currently Off
      value_template: "{{ is_state('input_select.sb_humidifier_mode', 'Off') }}"
    - condition: numeric_state 
      entity_id: sensor.sb_humidifier_humidity
      above: input_number.lrh_humidity_low_set
      below: input_number.lrh_humidity_high_set
    - condition: template # Water tank not empty
      value_template: "{{ is_state('sensor.sb_humidifier_lack_water', 'False') }}"
    - condition: template # Someone is home
      value_template: "{{ is_state('input_select.home_mode', 'Home') }}"
  action:
    service: input_select.select_option
    data_template:
      entity_id: input_select.sb_humidifier_mode
      option: High


- alias: 'SB Humidifier AM Off'
  trigger:
    - platform: state
      entity_id: binary_sensor.lrh_humidifier_am_automation_time_active
      to: 'off'
  condition:
    - condition: state # Only if AM automation is enabled
      entity_id: automation.sb_humidifier_am_schedule
      state: 'on'
    - condition: template # And only if humidifier is on
      value_template: '{{ states("input_select.sb_humidifier_mode") != "Off" }}'
  action:
    service: input_select.select_option
    data_template:
      entity_id: input_select.sb_humidifier_mode
      option: 'Off'

- alias: 'SB Humidifier PM Off'
  trigger:
    - platform: state
      entity_id: binary_sensor.lrh_humidifier_pm_automation_time_active
      to: 'off'
  condition:
    - condition: state # Only if PM automation is enabled
      entity_id: automation.sb_humidifier_pm_schedule
      state: 'on'
    - condition: template # And only if humidifier is on
      value_template: '{{ states("input_select.sb_humidifier_mode") != "Off" }}'
  action:
    service: input_select.select_option
    data_template:
      entity_id: input_select.sb_humidifier_mode
      option: 'Off'

This is how my lovelace looks like. Manual controls and automations are here. This is also taken from @ tom_l. I used decluttering-card. Make sure you have this installed and setup. You can do it without it, just follow what is in ui-lovelace.yaml and input the entities in lovelace.yaml below. The Humidifier Auotmation switch is what will turn on your am/pm automations. Make sure it is in the on position.

ui-lovelace.yaml

  humidifier_tpl:
    card:
      type: 'custom:vertical-stack-in-card'
      cards:
        - type: glance
          title: '[[title]]'
          state_color: false
          show_name: false
          entities:
            - entity: '[[entity_1]]'
              name: Humidifier
            - entity: '[[entity_2]]'
              name: Temperature
            - entity: '[[entity_3]]'
              name: Humidity
            - entity: '[[entity_4]]'
              name: Efficiency
        - entities:
            - head:
                label: Automation
                type: section
              items:
                - input_boolean.[[room]]_humidifier_automation_enable                                              
                - input_datetime.[[room]]_ac_am_on_time
                - input_datetime.[[room]]_ac_am_off_time
                - input_datetime.[[room]]_ac_pm_on_time
                - input_datetime.[[room]]_ac_pm_off_time
                - input_number.[[room]]_humidity_low_set                
                - input_number.[[room]]_humidity_high_set              
                - input_number.[[room]]_humidity_intensity_set
              type: 'custom:fold-entity-row'
          show_header_toggle: false
          type: entities

lovelace.yaml (file inside of lovelace folder)

  - type: custom:decluttering-card
    template: humidifier_tpl
    variables:
      - title: Humidifier Controls
      - room: lrh
      - entity_1: input_select.sb_humidifier_mode
      - entity_2: sensor.sb_humidifier_temperature
      - entity_3: sensor.sb_humidifier_humidity
      - entity_4: sensor.sb_humidifier_nebulization_efficiency
1 Like

Works perfect @gvandenhil Thanks.

Thanks for the great work all. My curtains and IR hub are all working great. I actually really like the way they handled their api too. Super simple. Get a token, get your device id’s, make rest calls. Wish every company did this.

Only final issue I have is that even though I’m using device class curtain, it’s showing me the icon for shade (like roller shades, rather than curtains like gvandenhill’s pics showed. Happening to any one else? Otherwise, perfect.

Disregard this message. Turns out my phone is too ancient and it ended up cropping out half the switchbot api token for some reason. Wasted a couple hours to figure that out :joy:

So I’m trying to set up my switchbot devices, but I keep getting {“message”:“Unauthorized”} with the command:

curl -H "Authorization: API_KEY_HERE" https://api.switch-bot.com/v1.0/devices

I tried resetting my token a couple times, making sure I copied it correctly every time. Hub is connected to wifi. Switchbot app is updated. Unfortunately I get the same unauthorized message whether using windows command prompt or home assistant terminal

Based on the SwitchBotApi github, {“message”:“Unauthorized”} means: Http 401 Error. User permission is denied due to invalid token.

I’ve tried your method, but the close button is still greyed out, regardless of the position of the curtains. I copied your YAML, so I have no idea what’s wrong. Do you?

sensor:
  - platform: rest
    name: 'Gordijnen positie'
    resource: !secret switchbot_gordijnen_status_url
    method: GET
    scan_interval: 60
    headers:
      Authorization: !secret switchbot_api
      Content-Type: 'application/json'
    value_template: >
      {% if value_json.body.slidePosition > 90 %} 0
      {% elif value_json.body.slidePosition < 10 %} 100
      {% else %} {{100-value_json.body.slidePosition}}
      {% endif %}
    json_attributes_path: "$.body"
    json_attributes:
      - deviceId
      - deviceType
      - hubDeviceId
      - calibrate
      - group
      - moving
      - slidePosition

rest_command:
  switchbot_device_command:
    url: 'https://api.switch-bot.com/v1.0/devices/{{ deviceId }}/commands'
    method: post
    content_type: 'application/json'
    headers:
      Authorization: !secret switchbot_api
    payload: '{"command": "{{ command }}","parameter": "{{ parameter }}"}'

cover:
  - platform: template
    covers:
      gordijnen:
        device_class: curtain
        friendly_name: "Gordijnen"
        unique_id: curtain.gordijnen
        position_template: "{{states('sensor.positie_gordijnen')}}"
        open_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_gordijnen_deviceId
            command: "turnOn"
        close_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_gordijnen_deviceId
            command: "turnOff"
        set_cover_position:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_gordijnen_deviceId
            command: "setPosition"
            parameter: "0,ff,{{100-position}}"

stop command not available in API as mentioned already by @gvandenhil, you can put back turnOff command = copy of close cover command

        stop_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_gordijnen_deviceId
            command: "turnOff"

I’ve been using this with my switchbot curtains and I was just wondering if there is a way to integrate the battery status into the solution? I couldn’t see it on a quick scan of the API but would be really helpful to integrate the battery status into my Home Assistant monitoring…

Hi there,

thanks for the great work. I put my meters and my hub (as IR-Controller) in ha. Most things are fine, but it would be nice, if the IR-Buttons work as ha-buttons and not like switches. Could you give me a hint, how i can use the HA-Buttons?

Hi all,

I was constantly struggling with the calibration of my curtains. It only happened with Home Assistant, so I knew it had to be specifically that. I’ve been messing around with the code for a little bit and now my curtains are completely closing again. It seems that turnOn and turnOff are not working properly.

I also saw the remarks about the greyed out close arrow. Since the API only asks for every 10 minutes, the arrow will be white/clickable after 10 minutes (in my experience). That’s where the stop button comes in handy. That one will always close your curtain.

Below the code for what I’m using (based on the different templates that I got here)

# Switchbot
rest_command:
  switchbot_device_command:
    url: 'https://api.switch-bot.com/v1.0/devices/{{ deviceId }}/commands'
    method: post
    content_type: 'application/json'
    headers:
      Authorization: !secret switchbot_api
    payload: '{"command": "{{ command }}","parameter": "{{ parameter }}"}'

sensor:
  - platform: rest
    name: 'Positie Woonkamer Gordijn'
    resource: !secret switchbot_woonkamergordijn_status_url
    method: GET
    scan_interval: 600
    headers:
      Authorization: !secret switchbot_api
      Content-Type: 'application/json'
    value_template: '{{ value_json.body.slidePosition }}'
    json_attributes_path: "$.body"
    json_attributes:
      - deviceId
      - deviceType
      - hubDeviceId
      - calibrate
      - group
      - moving
      - slidePosition

cover:
  - platform: template
    covers:
      bedroom_curtains:
        device_class: curtain
        friendly_name: "Woonkamergordijn"
        position_template: "{{ states('sensor.positie_woonkamer_gordijn') }}"
        open_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_woonkamergordijn_deviceId
            command: "setPosition"
            parameter: "0,ff,0"
        close_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_woonkamergordijn_deviceId
            command: "setPosition"
            parameter: "0,ff,100"
        stop_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_woonkamergordijn_deviceId
            command: "setPosition"
            parameter: "0,ff,100"
        set_cover_position:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_woonkamergordijn_deviceId
            command: "setPosition"
            parameter: "0,ff,{{position}}"

With warm regards,

Dennis

Can you please explain where meter1_json in states.sensor.meter1_json.attributes comes from?

For example, you have a name Meter1 JSON. Would everything still work if you were to name that SomethingRandom?