Switch-Bot API integration

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?

The name is automatically slugified ( → lower case, and spaces → underscores ) by the integration and used as the entity object id. e.g.

name: 'Any Name Here'

is converted to:

sensor.any_name_here

Where, sensor is the domain, and any_name_here is the object_id of the entity_id

entity_id: domain.object_id

As long as you realise that changing the name changes the entity_id you can change it to pretty much anything you want. Be careful with symbols (slugified to underscores), and try not to start your name with numbers. object_ids beginning with numbers require special treatment in some circumstances.

When i use rest command to open my curtains my switchbot open more than it should ( More than my Calibration) and wheels trying to spin even when it max on the rail :frowning: WHY? XD

I have 4 SwitchBot switches I use on some light switches that I’m having some difficulty properly integrating into HA and I’m hoping someone can help.

I got the device IDs by running this in in Terminal in macOS…

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

I then added this to secrets.yaml…

switchbot_api: "my_api_key"
switchbot_deviceId: "my_device_id"
switchbot_ryans_office_status_url: "https://api.switch-bot.com/v1.0/devices/my_device_id/status"

I then added this to 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 }}"}'

switch:
  - platform: template
    switches:
      ki_switchbot:
        friendly_name: Switchbot
        turn_on:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_deviceId
            command: "turnOn"
        turn_off:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_deviceId
            command: "turnOff"

I then added this to lovelace…

type: entities
entities:
  - entity: switch.ki_switchbot
    name: My Office
    secondary_info: last-changed
title: Switchbot Lights

… and it’s actually working!

1

However, I quickly realized that it’s not polling for updates so if I control it anywhere outside of HA it becomes out of sync and I’ve scanned through the dozens of posts above and see some sample code on how to poll for updates but I’m a bit unsure of how to actually apply it to configuration.yaml. Also as I have 4 different switches it seems a bit clunky to paste all the stuff above over and over again for each switch and I’m sure there is an easier way I’m just getting a bit twisted up trying to make it all work and looking for some help.

2 Likes

Anyone knows how to set 2 or more curtains?
I was able to follow the guide for only 1 pair of curtains. But what if I wanted to add another pair? If I type the same code twice, the first valid for the first pair and the second valid for the second pair, Home Assistant gives me an error.

The problem is the curtain position number. Home assistant is expecting position 0 to be closed and 100 to be open, where as switchbot reports it the opposite way round.
Refer to Template Cover - Home Assistant

position_template:
Defines a template to get the position of the cover. Legal values are numbers between “0” (closed) and “100” (open).

Switchbot reports 0 as open and 100 as closed.

The fix is to use the following in the position_template.

cover:
  - platform: template
    covers:
      bedroom_curtains:
      device_class: curtain
        friendly_name: "Bedroom Curtains"
        #position_template: "{{ states('sensor.bedroom_curtain_position') }}" # original
        position_template:  "{% if  (states('sensor.bedroom_curtain_position') | round | int) == 0 %}
                             100
                             {% else %}
                             {{  100 % (states('sensor.bedroom_curtain_position') | round | int) }}
                             {% endif %}" # my change using % (mod) to convert the value. if value is 0 it throws error in log about using mod on a value of 0. so place in the static value instead.
        open_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_bedroom_deviceId
            command: "turnOn"
        close_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_bedroom_deviceId
            command: "turnOff"
        stop_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_bedroom_deviceId
            command: "turnOff"
        set_cover_position:
          service: rest_command.switchbot_device_command

The mod (%) math function provides the remainder value. You can google the mod math function but effectively it does the following.

{{ 100 % (states(‘sensor.bedroom_curtain_position’) | round | int) }}

100 % 99 = 1
100 % 98 = 2
100 % 90 = 10
100 % 50 = 50
100 % 30 = 70
100 % 5 = 95
100 % 2 = 98
100 % 0 = 100

It effectively converts/switches the slider position to one compliant with home assistant. It works great on my curtains using the api.

Really Hope people find this helpful. I know this bothered my when interacting with curtains on my lovelace dashboard. This resolve it completely.

Did you make it work?

I own about ten Switchbot Meters, but for some reason both the frequency of measurements wildly varies throughout the day both on the app, but especially when using the API. Is there anyone else also having these issues? The signal needs to only travel through one wall in one case, but in another case it goes through two.

It’s almost as if someone bought a signal jammer to mess up everything. Of course, it’s possible that the large set of wireless technologies being used means that I am creating this problem myself without knowing about it.

Wireless systems in use: multiple (<5) wireless routers (2.4Ghz), zigbee coordinator, multiple Switchbot hubs, multiple accesspoints, multiple ESP32s running a Bluetooth4+ stacks + acting as WiFI client.

The environment is fairly public, so “anyone” could theoretically bring a signal jammer. It’s more likely that someone just has a malfunctioning device or that there is some kind of interference from having too many devices.

Has anybody been able to find a way to get the battery level of the switchbot curtain or meter into home assistant ?

I’ve got a curtain and meter working but would like to display the battery level on my dashboard.

Charging and/or solar panel connection would be awesome too :smiley:

I’m getting this error in the log when trying to use your mod:

Logger: homeassistant.helpers.template
Source: helpers/template.py:1286
First occurred: 14:24:53 (4 occurrences)
Last logged: 14:24:53

  • Template warning: ‘round’ got invalid input ‘unknown’ when rendering template ‘{% if (states(‘sensor.livingroom_curtain_position’) | round | int) == 0 %} 100 {% else %} {{ 100 % (states(‘sensor.livingroom_curtain_position’) | round | int) }} {% endif %}’ but no default was specified. Currently ‘round’ will return ‘unknown’, however this template will fail to render in Home Assistant core 2022.1
  • Template warning: ‘int’ got invalid input ‘unknown’ when rendering template ‘{% if (states(‘sensor.livingroom_curtain_position’) | round | int) == 0 %} 100 {% else %} {{ 100 % (states(‘sensor.livingroom_curtain_position’) | round | int) }} {% endif %}’ but no default was specified. Currently ‘int’ will return ‘0’, however this template will fail to render in Home Assistant core 2022.1

Any ideas of how to fix?

How did you name your sensor?

I have this working with my switchbot switch, but has anyone gotten the status to work with the switch? I’m still pretty new to home assistant and I’m not sure where to add the api status check.

Edit:

I think I have this working, someone please let me know if there is a better way to do this. Here is my config.yaml.

Looks like they updated their API to allow 10,000 polls a day so I have my single switch checking every 10 seconds. I’m also leaving out my secrets.yaml because it’s the same as the examples above.

@BlueWave this might solve your question as well.

#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 }}"}'
    
sensor:
  - platform: rest
    name: 'switch_status'
    resource: !secret switchbot_status_url
    method: GET
    scan_interval: 10
    headers:
      Authorization: !secret switchbot_api
      content_type: "application/json"
    json_attributes_path: "$.body"
    value_template: '{{ value_json.body.power }}'
    json_attributes:
      - deviceId
      - deviceType
      - hubDeviceId
      - power


switch:
  - platform: template
    switches:
      buttkicker_power:
        friendly_name: Buttkicker Power
        value_template: "{{ is_state('sensor.switch_status', 'on') }}"
        turn_on:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_deviceId
            command: "turnOn"
        turn_off:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_deviceId
            command: "turnOff"

I saw some questions of people who are having another Switchbot curtain in another room, as I have too… I did not see any reponses. Can someone help with this code? Thanks a lot!

Something like this?

sensor:
  - platform: rest
    name: 'Positie Woonkamer Gras Gordijn'
    resource: !secret switchbot_woonkamer_gras_gordijn_status_url
    method: GET
    scan_interval: 30
    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    
  - platform: rest
    name: 'Positie Woonkamer Water Gordijn'
    resource: !secret switchbot_woonkamer_water_gordijn_status_url
    method: GET
    scan_interval: 30
    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:
      woonkamer_gras_gordijn:
        device_class: curtain
        friendly_name: "Woonkamer gras gordijn"
        #position_template: "{{ states('sensor.positie_woonkamer_gordijn') }}"
        position_template:  "{% if  (states('sensor.positie_woonkamer_gras_gordijn') | round | int) == 0 %}
                             100
                             {% else %}
                             {{  100 % (states('sensor.positie_woonkamer_gras_gordijn') | round | int) }}
                             {% endif %}" # my change using % (mod) to convert the value. if value is 0 it throws error in log about using mod on a value of 0. so place in the static value instead.
        open_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_woonkamer_gras_gordijn_deviceId
            command: "setPosition"
            parameter: "0,ff,0"
        close_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_woonkamer_gras_gordijn_deviceId
            command: "setPosition"
            parameter: "0,ff,100"
        stop_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_woonkamer_gras_gordijn_deviceId
            command: "turnOff"
        set_cover_position:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_woonkamer_gras_gordijn_deviceId
            command: "setPosition"
            parameter: "0,ff,{{position}}"
  - platform: template
    covers:
      woonkamer_water_gordijn:
        device_class: curtain
        friendly_name: "Woonkamer water gordijn"
#        position_template: "{{ states('sensor.positie_woonkamer_water_gordijn') }}"
        position_template:  "{% if  (states('sensor.positie_woonkamer_water_gordijn') | round | int) == 0 %}
                             100
                             {% else %}
                             {{  100 % (states('sensor.positie_woonkamer_water_gordijn') | round | int) }}
                             {% endif %}" # my change using % (mod) to convert the value. if value is 0 it throws error in log about using mod on a value of 0. so place in the static value instead.
        open_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_woonkamer_water_gordijn_deviceId
            command: "setPosition"
            parameter: "0,ff,0"
        close_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_woonkamer_water_gordijn_deviceId
            command: "setPosition"
            parameter: "0,ff,100"
        stop_cover:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_woonkamer_water_gordijn_deviceId
            command: "turnOff"
        set_cover_position:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_woonkamer_water_gordijn_deviceId
            command: "setPosition"
            parameter: "0,ff,{{position}}"
1 Like

perfect! thanks!

I bought a new Switchbot LED Lightstrip and created an entry for the REST sensor.

  - platform: rest
    name: "Switchbot Lightstrip"
    resource: !secret switchbot_Lightstrip_status_url
    method: GET
    scan_interval: 5
    headers:
      Authorization: !secret switchbot_api
      Content-Type: "application/json"
    value_template: "{{ value_json.body }}"
    json_attributes_path: "$.body"
    json_attributes:
      - deviceId 
      - deviceType
      - hubDeviceId
      - power
      - brightness
      - color

Can somebody please support me in creating a template in order to control the light especially the color?

I’ve further worked on a template for the lighstrip.
Turn on/off is now working

Only two things are still not working. Can somebody please give a hint why i can not adjust brightness and color?

light:
  - platform: template
    lights:
      switchbot_lightstrip:
        friendly_name: Lichtstreifen Signe Büro
        unique_id: Lichtstreifen Signe Büro
        turn_on:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_lightstrip_deviceId
            command: "turnOn"
        turn_off:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_lightstrip_deviceId
            command: "turnOff"
        set_level:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_lightstrip_deviceId
            command: "setBrightness"
            parameter: "{1-100}"
        set_color:
          service: rest_command.switchbot_device_command
          data:
            deviceId: !secret switchbot_lightstrip_deviceId
            command: "setColor"
            parameter: "{0-255}:{0-255}:{0-255}"

Thanks!! I was bummed that I couldn’t use the BT integration since I’m running Hyper-V but this works perfectly. Using “press” mode:

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 }}","commandType": "{{ commandType }}"}'

scripts.yaml

switchbot_aircon:
  alias: Switchbot Aircon
  sequence:
  - service: rest_command.switchbot_device_command
    data:
      deviceId: !secret switchbot_aircon_deviceId
      command: press
      parameter: default
      commandType: command

Hey guys,

I’ve been trying to get the temperature working for my IR aircon.
Besides creating the rest_command and switch in the config I created a climate/generic_thermostat like this:

climate:
  - platform: generic_thermostat
    name: Airco Slaapkamer
    heater: switch.airco_slaapkamer
    target_sensor: sensor.airpurifier_mc1_temperature
    min_temp: 17
    max_temp: 23
    ac_mode: true
    target_temp: 19
    initial_hvac_mode: "off"
    precision: 1

In this particular case I used our air purifier as temperature sensor, but it’s probably best to use a zigbee or BLE temperature sensor instead. I’m still testing it, but so far it seems to work.