devWaves / SwitchBot-MQTT-BLE-ESP32

Allows for multiple SwitchBot bots and curtains to be controlled via MQTT sent to ESP32. ESP32 will send BLE commands to switchbots and return MQTT responses to the broker. Also supports Temperature, Motion, Contact sensors
MIT License
531 stars 66 forks source link

Integration into ESPHome #44

Closed samip5 closed 2 years ago

samip5 commented 2 years ago

I'm intrigued by this piece of software, and I would love to be able to integrate it into my CC2652 POE Coordinator, that's running ESP32 with a CC2652 Zigbee module in it as well.

Has anyone attempted this yet?

iMicknl commented 2 years ago

See https://github.com/esphome/feature-requests/issues/454.

We didn't make any progress yet, so if you are able to help, all help is welcome. 😉

ppanagiotis commented 2 years ago

Almost there https://github.com/esphome/esphome/pull/3398

robbinonline commented 2 years ago

Should be working now? It would be awesome if this would be intergraded into ESPHome for updates and editing.

ppanagiotis commented 2 years ago

@robbinonline yes it is working. not merged yet but with this branch and this config

ble_client:
  - mac_address: XX:XX:XX:XX:XX:XX
    id: cover
    maintain_connection: false

cover:                                                                            
  - platform: template                                                             
    name: cover_test                                   
    optimistic: true                                                               
    open_action:                                                                
      - ble_client.ble_write:                                                      
          id: cover
          service_uuid: CBA20D00-224D-11E6-9FB8-0002A5D5C51B                       
          characteristic_uuid: CBA20002-224D-11E6-9FB8-0002A5D5C51B                
          # List of bytes to write.                                                
          value: [0x57, 0x0F, 0x45, 0x01, 0x05, 0xFF, 0x00]                        
    close_action:                                                                    
      - ble_client.ble_write:                                                      
          id: cover                                                      
          service_uuid: CBA20D00-224D-11E6-9FB8-0002A5D5C51B                       
          characteristic_uuid: CBA20002-224D-11E6-9FB8-0002A5D5C51B                
          # List of bytes to write.                                                
          value: [0x57, 0x0F, 0x45, 0x01, 0x05, 0xFF, 0x64] 
    stop_action:
      - ble_client.ble_write:                                                      
          id: cover                                                      
          service_uuid: CBA20D00-224D-11E6-9FB8-0002A5D5C51B                       
          characteristic_uuid: CBA20002-224D-11E6-9FB8-0002A5D5C51B                
          # List of bytes to write.                                                
          value: [0x57, 0x0F, 0x45, 0x01, 0x00, 0xFF]  

Works great!

robbinonline commented 2 years ago

@ppanagiotis Thanks! I have to found out how to use this branch in hacs and then give it a try!

Ulrar commented 2 years ago

@robbinonline I don't know if you've figured it out, but I created a quick repo with those changes that you can use directly from your esphome config :

external_components:
  - source:
      type: git
      url: https://github.com/Ulrar/esphome-temp.git
      ref: ble_write_action
    components: [ ble_client ]

The only change I made myself is hardcoding the const.py change so it can be imported as an external components while we wait for it to be merged. Seems to work well with switchbot curtains so far for me.

I'll add that you probably want some extra code to parse the BLE advertisements sent by the curtains for both the battery level and the current status (open / close), here's what my config looks like for that :

sensor:    
  - platform: template
    name: $sbcbw Right Battery
    id: ${sbcbw_nospace}_right_battery
    unit_of_measurement: '%'
    device_class: battery
    accuracy_decimals: 0
    icon: "mdi:battery"
    update_interval: 180s

  - platform: template
    name: $sbcbw Left Battery
    id: ${sbcbw_nospace}_left_battery
    unit_of_measurement: '%'
    device_class: battery
    accuracy_decimals: 0
    icon: "mdi:battery"
    update_interval: 180s

esp32_ble_tracker:
  id: $device_name
  scan_parameters:
    interval: 320ms
    window: 320ms    
  on_ble_advertise:
    - mac_address: !secret curtain_bay_window_mac
      then:
        - lambda: |-
            switchbot_curtain( &x
                             , id(${sbcbw_nospace}_cover)
                             , id(${sbcbw_nospace}_left_battery)
                             );
    - mac_address: !secret curtain2_bay_window_mac
      then:
        - lambda: |-
            switchbot_battery_only(&x, id(${sbcbw_nospace}_right_battery));

ble_client:
  - mac_address: !secret curtain_bay_window_mac
    id: ${sbcbw_nospace}
    maintain_connection: false

cover:
  - platform: template
    id: ${sbcbw_nospace}_cover
    device_class: curtain
    name: ${sbcbw}                                                      
    optimistic: true
    has_position: true
    open_action:                                                             
      - ble_client.ble_write:                                                   
          id: ${sbcbw_nospace}                                                        
          service_uuid: CBA20D00-224D-11E6-9FB8-0002A5D5C51B
          characteristic_uuid: CBA20002-224D-11E6-9FB8-0002A5D5C51B
          value: [0x57, 0x0F, 0x45, 0x01, 0x05, 0xFF, 0x00]                     
    close_action:                                                            
      - ble_client.ble_write:                                                   
          id: ${sbcbw_nospace}                                                          
          service_uuid: CBA20D00-224D-11E6-9FB8-0002A5D5C51B
          characteristic_uuid: CBA20002-224D-11E6-9FB8-0002A5D5C51B
          value: [0x57, 0x0F, 0x45, 0x01, 0x05, 0xFF, 0x64]
    position_action:
      - ble_client.ble_write:
          id: ${sbcbw_nospace}        
          service_uuid: cba20d00-224d-11e6-9fb8-0002a5d5c51b
          characteristic_uuid: cba20002-224d-11e6-9fb8-0002a5d5c51b
          value: !lambda |-
            uint8_t byte_position = 100  * (1.0f - pos);
            ESP_LOGW("POS: ", "pos: %f, byte_position: %d", pos, byte_position);
            return {0x57, 0x0F, 0x45, 0x01, 0x05, 0xFF, byte_position};

And here's the code for those two functions called from the lambdas :

void switchbot_battery_only( const esp32_ble_tracker::ESPBTDevice *x
                           , esphome::template_::TemplateSensor* batteryEnt
                           )
{
    for (auto data : x->get_service_datas())
    {
        batteryEnt->publish_state(data.data[2] & 0b01111111);
    }
}

void switchbot_curtain( const esp32_ble_tracker::ESPBTDevice *x
            , esphome::template_::TemplateCover *curtainEnt
            , esphome::template_::TemplateSensor* batteryEnt
            )
{
    for (auto data : x->get_service_datas())
    {
        if(data.data.size() == 6)
        {
            int8_t battLevel = 0;
            int8_t position = 0;

            battLevel = data.data[2] & 0b01111111;
            position = data.data[3] & 0b01111111;

            curtainEnt->position = (100 - position) / 100;
            curtainEnt->publish_state();
            batteryEnt->publish_state(battLevel);
        }
    }
}

This is all very much a work in progress but with that I have proper cover entities working (and displaying their open/close status correctly in home assistant) for the curtains, and I'm getting the battery level for both switchbots.

The switchbot app doesn't display the mac address of the second curtain bot when they're groupped for one window, I used nRF Connect on my phone to find it. Another option would be to ungroup them, write it down then re-group them I guess.

I have more code to handle contact sensors as well, if anyone is interested. I wonder what it'd take to make all of this into a generic switchbot component, it'd depend on rbaron's PRs getting merged but it would be nice.

Ulrar commented 1 year ago

For anyone following this I've updated my branch with @rbaron's latest changes, and updated my comment above to add the position action. Switchbots can now be set to any % using the slider in home assistant, thanks rbaron !