How to setup ESPHome to control my Bluetooth controlled (Octocontrol) bed

I only have one connected ‘[0]’ only. Based on the information you’ve shared I’d expect you also to have 0 or possibly 1

I’m able to control my bed, but it’s going wild when I press a button. It’s not stopping controlling the bed and with the ‘delay’ it’s shocking (start/stop/start/stop).

I have to unplug the ESP32 to get the bed under control. I thought I could just ‘hold’ the button to control it and when I let go it stops. Anyone any idea?

The/my original remote is sending commands multiple times per second. That’s why I send it every 300ms for 30 seconds.
I do recognize that when I first send ‘up’ and within the 30 seconds ‘down’ it will send up/down/up/down commands, which is not good… I still need to work on preventing that…
Is that what happened on your side?

I think that may be part of the issue indeed. Trying to thinker further on how to make this smooth.

Is there a way within ESPhome, like with the actual physical remote, to ‘on_hold’ the button and it stops when you release?

If you attach a button to ESPHome you can use Binary Sensor Component — ESPHome
I do not see how to do this with a button in home assistant

I noticed that most of the script (snippets) above work when there is a connection made manually by using the Octo app but after a (short) while the connection drops off. It seems like - when I look at the Octo app - there is no ‘binding’ saved by ESPHome

(Strangely, the light control continues to work though)

Anyone know how to store or save the binding?

I do not completely understand, do you use Octo app and HA in parallel?
Why would you need a binding? The ‘esp32_ble_tracker:’ keeps scanning periodically

If I understand you correctly, you first connect using the Octo app and then get things working in HA, and not without the use of the app?

I can control the light easily. (as some also stated) but when I send a command by either button/switch (template) - nothing happens. When I turn on the app - which is connected to my bed - the commands do work when I send a command by either button/switch in hassio.

The connection becomes active by the ble scan

Do you have the repeat active?
One time sending will not completely move the bed
Connection

I tested it again, when I turn on the app and control the bed my YAML-code works, until it loses connection when I close the app.

This is the code I’m currently trying out:


# Enable Bluetooth scanning for this ESP32
# BLE Tracker
esp32_ble_tracker:
  # scan_parameters:
  #   interval: 40ms  # Increase the interval to reduce scanning frequency
  #   window: 30ms  # Shorten the window to limit the time spent scanning

  # on_ble_advertise:
  #   - mac_address: xx:xx:xx:xx:xx:xx
  #     then:
  #       - lambda: |-
  #           ESP_LOGD("ble_adv", "Detected BLE device: %s", x.address_str().c_str());
  #           ESP_LOGD("ble_adv", "  Name: %s", x.get_name().c_str());
  #           ESP_LOGD("ble_adv", "  Service UUIDs:");
  #           for (auto uuid : x.get_service_uuids()) {
  #             ESP_LOGD("ble_adv", "    - %s", uuid.to_string().c_str());
  #           }
  #           ESP_LOGD("ble_adv", "  Service Data:");
  #           for (auto data : x.get_service_datas()) {
  #             ESP_LOGD("ble_adv", "    - %s: (length %i)", data.uuid.to_string().c_str(), data.data.size());
  #           }
  #           ESP_LOGD("ble_adv", "  Manufacturer Data:");
  #           for (auto data : x.get_manufacturer_datas()) {
  #             ESP_LOGD("ble_adv", "    - %s: (length %i)", data.uuid.to_string().c_str(), data.data.size());
  #           }

# BLE Client
ble_client:
  - mac_address:  xx:xx:xx:xx:xx:xx
    id: rc2bedpeter
    on_connect:
      then:
        - logger.log: "Connected to the Bluetooth receiver"
        - esp32_ble_tracker.stop_scan  # Stop BLE scanning after connecting
    on_disconnect:
      then:
        - logger.log: "Disconnected from the Bluetooth receiver"
        - esp32_ble_tracker.start_scan  # Re-enable BLE scanning when disconnected
    auto_connect: true  # Automatically try to reconnect if the connection is lost

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO12  # Replace with your actual GPIO pin number
      mode: INPUT_PULLUP
    id: control_bed_head_up_sensor
    name: "Control Bed Head Up Sensor"
    on_press:
      - script.execute: control_bed_head_up
    on_release:
      - script.execute: control_bed_stop_cmd

  - platform: gpio
    pin:
      number: GPIO13  # Replace with your actual GPIO pin number
      mode: INPUT_PULLUP
    id: control_bed_head_down_sensor
    name: "Control Bed Head Down Sensor"
    on_press:
      - script.execute: control_bed_head_down
    on_release:
      - script.execute: control_bed_stop_cmd

  - platform: status
    id: ble_connection_status
    name: "BLE Connection Status"

switch:
  - platform: template
    name: "Bed verlichting Peter"
    id: bed_verlichting_peter
    icon: "mdi:lightbulb-outline"
    optimistic: true
    turn_on_action:
      - ble_client.ble_write:
          id: rc2bedpeter
          service_uuid: ffe0
          characteristic_uuid: ffe1
          value: [0x40, 0x20, 0x72, 0x00, 0x08, 0xde, 0x00, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40]
    turn_off_action:
      - ble_client.ble_write:
          id: rc2bedpeter
          service_uuid: ffe0
          characteristic_uuid: ffe1
          value: [0x40, 0x20, 0x72, 0x00, 0x08, 0xdf, 0x00, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x40]

button:
  - platform: template
    name: "Bed Peter head up"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed
          section: 1  # head
          direction: 1  # up

  - platform: template
    name: "Bed Peter head down"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed
          section: 1  # head
          direction: 0  # down

  - platform: template
    name: "Bed Peter head/feet up"
    icon: "mdi:bed"
    on_press:
      - ble_client.ble_write:
          id: rc2bedpeter
          service_uuid: ffe0
          characteristic_uuid: ffe1
          value: [0x40, 0x02, 0x70, 0x00, 0x01, 0x07, 0x06, 0x40]

  - platform: template
    name: "Bed Peter head/feet down"
    icon: "mdi:bed"
    on_press:
      - ble_client.ble_write:
          id: rc2bedpeter
          service_uuid: ffe0
          characteristic_uuid: ffe1
          value: [0x40, 0x02, 0x71, 0x00, 0x01, 0x06, 0x06, 0x40]

  - platform: template
    name: "Bed Peter feet up"
    icon: "mdi:bed"
    on_press:
      - ble_client.ble_write:
          id: rc2bedpeter
          service_uuid: ffe0
          characteristic_uuid: ffe1
          value: [0x40, 0x02, 0x70, 0x00, 0x01, 0x09, 0x04, 0x40]

  - platform: template
    name: "Bed Peter feet down"
    icon: "mdi:bed"
    on_press:
      - ble_client.ble_write:
          id: rc2bedpeter
          service_uuid: ffe0
          characteristic_uuid: ffe1
          value: [0x40, 0x02, 0x71, 0x00, 0x01, 0x08, 0x04, 0x40]

  - platform: template
    name: "Bed Peter end move"
    id: bed_peter_end_move
    icon: "mdi:stop-circle-outline"
    on_press:
      - ble_client.ble_write:
          id: rc2bedpeter
          service_uuid: ffe0
          characteristic_uuid: ffe1
          value: [0x40, 0x02, 0x73, 0x00, 0x00, 0x0b, 0x40]

script:
  - id: control_bed
    mode: restart
    parameters:
      section: int  # 1 head, 2 feet, 3 both
      direction: int  # 1 up, 0 down
    then:
      - ble_client.ble_write:  # send stop command
          id: rc2bedpeter
          service_uuid: ffe0
          characteristic_uuid: ffe1
          value: [0x40, 0x02, 0x73, 0x00, 0x00, 0x0b, 0x40]
      - lambda: |-
          switch (section) {
            case 1: if (direction == 1) { 
              id(control_bed_head_up).execute();
              return;
            } else {
              id(control_bed_head_down).execute();
              return;
            }
            case 2: if (direction == 1){ 
              id(control_bed_feet_up).execute();
              return;
            } else {
              id(control_bed_feet_down).execute();
              return;
            }
            case 3: if (direction == 1){ 
              id(control_bed_both_up).execute();
              return;
            } else {
              id(control_bed_both_down).execute();
              return;
            }
            default: {      
              id(control_bed_stop_cmd).execute();
              return;
            }
          }
  - id: control_bed_head_up
    mode: restart
    then:
      - repeat:
          count: 100
          then:
            - ble_client.ble_write:
                id: rc2bedpeter
                service_uuid: ffe0
                characteristic_uuid: ffe1
                value: [0x40, 0x02, 0x70, 0x00, 0x01, 0x0b, 0x02, 0x40]
            - delay: 300ms
            - logger.log: "repeat head UP"
  - id: control_bed_head_down
    mode: restart
    then:
      - repeat:
          count: 100
          then:
            - ble_client.ble_write:
                id: rc2bedpeter
                service_uuid: ffe0
                characteristic_uuid: ffe1
                value: [0x40, 0x02, 0x71, 0x00, 0x01, 0x0a, 0x01, 0x40]
            - delay: 300ms
            - logger.log: "repeat head DOWN"
  - id: control_bed_feet_up
    mode: restart
    then:
      - repeat:
          count: 100
          then:
            - ble_client.ble_write:
                id: rc2bedpeter
                service_uuid: ffe0
                characteristic_uuid: ffe1
                value: [0x40, 0x02, 0x70, 0x00, 0x01, 0x08, 0x01, 0x40]
            - delay: 300ms
            - logger.log: "repeat feet UP"
  - id: control_bed_feet_down
    mode: restart
    then:
      - repeat:
          count: 100
          then:
            - ble_client.ble_write:
                id: rc2bedpeter
                service_uuid: ffe0
                characteristic_uuid: ffe1
                value: [0x40, 0x02, 0x71, 0x00, 0x01, 0x07, 0x01, 0x40]
            - delay: 300ms
            - logger.log: "repeat feet DOWN"
  - id: control_bed_both_up
    mode: restart
    then:
      - repeat:
          count: 100
          then:
            - ble_client.ble_write:
                id: rc2bedpeter
                service_uuid: ffe0
                characteristic_uuid: ffe1
                value: [0x40, 0x02, 0x70, 0x00, 0x01, 0x0a, 0x01, 0x40]
            - delay: 300ms
            - logger.log: "repeat both UP"
  - id: control_bed_both_down
    mode: restart
    then:
      - repeat:
          count: 100
          then:
            - ble_client.ble_write:
                id: rc2bedpeter
                service_uuid: ffe0
                characteristic_uuid: ffe1
                value: [0x40, 0x02, 0x71, 0x00, 0x01, 0x09, 0x01, 0x40]
            - delay: 300ms
            - logger.log: "repeat both DOWN"
  - id: control_bed_stop_cmd
    mode: restart
    then:
      - ble_client.ble_write:
          id: rc2bedpeter
          service_uuid: ffe0
          characteristic_uuid: ffe1
          value: [0x40, 0x02, 0x73, 0x00, 0x00, 0x0b, 0x40]
      - logger.log: "Bed stopped"

I expect you did fill the right MAC addresses?
I’m not sure what the effect of commenting the ble scan parameters is?
What do you see when the following part is not commented out? (The ble advertise part)
Do you see connection status in the logging?
Why do you stop ble scan upon first connect? If the connection gets lost it will not reconnect

The code above is pretty messy, I can share my cleaned-up version end of the week (please remind me if I forget)

He! Yes, I did fill in the right Mac address :slight_smile:

I’ve been playing around with many ble configurations. Yes, I have adjusted that by commenting that out (stop ble scan).

Three hypotheses I have:

  1. You have to press the star2 connected twice to ‘pair’ or ‘add’ another remote. Both for the app and for the physcial remote. So maybe it has something to do with this.
  2. There is something wrong the yaml-code and to connect it needs some specific connection sequence
  3. The ESPHome’s command structure might not be perfectly matching what the bed expects. Maybe the app uses a slightly different format or timing for the commands.

I’ve updated my automation

  • Adding second bed (including connection state monitor)
  • General cleanup and fixing not working parts (I was only using the had movement part)
  • Preventing issues by user sending parallel up-and down commands on the same part of the bed
  • Mind head-up-movement for bed_Annick is limited in height
esphome:
  name: esp-bedcontrol
  friendly_name: esp-bedcontrol

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxxxxxxxxxxxxx"

ota:
  - platform: esphome
    password: "xxxxxxxxxxxxxxxxxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esp-Bedcontrol Fallback Hotspot"
    password: "xxxxxxxxxxxxxxxxxx"

captive_portal:
    
esp32_ble_tracker:
  scan_parameters:
    duration: 30s
#FOR DEBUG ONLY:
#  on_ble_advertise:
#    - mac_address: xx:xx:xx:xx:xx:xx
#      then:
#        - lambda: |-
#            ESP_LOGD("ble_adv", "New BLE device");
#            ESP_LOGD("ble_adv", "  address: %s", x.address_str().c_str());
#            ESP_LOGD("ble_adv", "  name: %s", x.get_name().c_str());
#            ESP_LOGD("ble_adv", "  Advertised service UUIDs:");
#            for (auto uuid : x.get_service_uuids()) {
#                ESP_LOGD("ble_adv", "    - %s", uuid.to_string().c_str());
#            }
#            ESP_LOGD("ble_adv", "  Advertised service data:");
#            for (auto data : x.get_service_datas()) {
#                ESP_LOGD("ble_adv", "    - %s: (length %i)", data.uuid.to_string().c_str(), data.data.size());
#            }
#            ESP_LOGD("ble_adv", "  Advertised manufacturer data:");
#            for (auto data : x.get_manufacturer_datas()) {
#                ESP_LOGD("ble_adv", "    - %s: (length %i)", data.uuid.to_string().c_str(), data.data.size());
#            }
#  on_ble_manufacturer_data_advertise:
#    - mac_address: xx:xx:xx:xx:xx:xx
#      manufacturer_id: 0590
#      then:
#        - lambda: |-
#            if (x[0] != 0x7b || x[1] != 0x61) return;
#            int value = x[2] + (x[3] << 8);
#            id(ble_sensor).publish_state(value);
#  on_ble_service_data_advertise:
#    - mac_address: xx:xx:xx:xx:xx:xx
#      service_uuid: 181A
#      then:
#        - lambda: 'id(ble_sensor).publish_state(x[0]);'
#  on_scan_end:
#    - then:
#        - lambda: |-
#             ESP_LOGD("ble_auto", "The scan has ended!");
#
#sensor:
#  - platform: template
#    name: "BLE Sensor"
#    id: ble_sensor

binary_sensor:
  - platform: template
    name: "Bed Annick remote connection status"
    id: bed_annick_remote_connection_status
  - platform: template
    name: "Bed Peter remote connection status"
    id: bed_peter_remote_connection_status

ble_client:
  - mac_address: xx:xx:xx:xx:xx:xx
    id: rc2bedannick
    on_connect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Connected to BLE device Annick");
        - binary_sensor.template.publish:
            id: bed_annick_remote_connection_status
            state: True
    on_disconnect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Disconnected from BLE device Annick");
        - binary_sensor.template.publish:
            id: bed_annick_remote_connection_status
            state: False
  - mac_address: xx:xx:xx:xx:xx:xx
    id: rc2bedpeter
    on_connect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Connected to BLE device Peter");
        - binary_sensor.template.publish:
            id: bed_peter_remote_connection_status
            state: True
    on_disconnect:
      then:
        - lambda: |-
            ESP_LOGD("ble_client_lambda", "Disconnected from BLE device Peter");
        - binary_sensor.template.publish:
            id: bed_peter_remote_connection_status
            state: False

switch:
  - platform: template
    name: "Bed verlichting Annick"
    id: bed_verlichting_annick
    icon: "mdi:lightbulb-outline"
    optimistic: true
    turn_on_action:
      - ble_client.ble_write:
          id: rc2bedannick
          service_uuid: ffe0
          characteristic_uuid: ffe1
          # List of bytes to write.
          value: [0x40, 0x20, 0x72, 0x00, 0x08, 0xde, 0x00, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40]
    turn_off_action:
      - ble_client.ble_write:
          id: rc2bedannick
          service_uuid: ffe0
          characteristic_uuid: ffe1
          # List of bytes to write.
          value: [0x40, 0x20, 0x72, 0x00, 0x08, 0xdf, 0x00, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x40]
  - platform: template
    name: "Bed verlichting Peter"
    id: bed_verlichting_peter
    icon: "mdi:lightbulb-outline"
    optimistic: true
    turn_on_action:
      - ble_client.ble_write:
          id: rc2bedpeter
          service_uuid: ffe0
          characteristic_uuid: ffe1
          # List of bytes to write.
          value: [0x40, 0x20, 0x72, 0x00, 0x08, 0xde, 0x00, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40]
    turn_off_action:
      - ble_client.ble_write:
          id: rc2bedpeter
          service_uuid: ffe0
          characteristic_uuid: ffe1
          # List of bytes to write.
          value: [0x40, 0x20, 0x72, 0x00, 0x08, 0xdf, 0x00, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x40]

button:
  - platform: template
    name: "Bed Annick head up"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed_annick
          section: 1 #head
          direction: 1 #up
  - platform: template
    name: "Bed Peter head up"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed_peter
          section: 1 #head
          direction: 1 #up
  - platform: template
    name: "Bed Annick head down"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed_annick
          section: 1 #head
          direction: 0 #down
  - platform: template
    name: "Bed Peter head down"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed_peter
          section: 1 #head
          direction: 0 #down
  - platform: template
    name: "Bed Annick head/feet up"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed_annick
          section: 3 #head/feet
          direction: 1 #up
  - platform: template
    name: "Bed Peter head/feet up"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed_peter
          section: 3 #head/feet
          direction: 1 #up
  - platform: template
    name: "Bed Annick head/feet down"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed_annick
          section: 3 #head/feet
          direction: 0 #down
  - platform: template
    name: "Bed Peter head/feet down"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed_peter
          section: 3 #head/feet
          direction: 0 #down
  - platform: template
    name: "Bed Annick feet up"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed_annick
          section: 2 #feet
          direction: 1 #down
  - platform: template
    name: "Bed Peter feet up"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed_peter
          section: 2 #feet
          direction: 1 #down
  - platform: template
    name: "Bed Annick feet down"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed_annick
          section: 2 #feet
          direction: 0 #down
  - platform: template
    name: "Bed Peter feet down"
    icon: "mdi:bed"
    on_press:
      - script.execute:
          id: control_bed_peter
          section: 2 #feet
          direction: 0 #down
  - platform: template
    name: "Bed Annick end move"
    id: bed_annick_end_move
    icon: "mdi:stop-circle-outline"
    on_press:
      - logger.log: "Stopping all commands for bed Annick"
      - script.execute: control_bed_annick_stop_cmd
  - platform: template
    name: "Bed Peter end move"
    id: bed_peter_end_move
    icon: "mdi:stop-circle-outline"
    on_press:
      - logger.log: "Stopping all commands for bed Peter"
      - script.execute: control_bed_peter_stop_cmd

script:
  - id: control_bed_annick
    mode: restart 
    parameters:
      section: int #1 head, 2 feet, 3 both
      direction: int # 1 up, 0 down
    then:
      - ble_client.ble_write: #send stop command
          id: rc2bedannick
          service_uuid: ffe0
          characteristic_uuid: ffe1
          # List of bytes to write.
          value: [0x40, 0x02, 0x73, 0x00, 0x00, 0x0b, 0x40]
      # Check what task to perform
      - lambda: |-
          switch (section) {
            case 1: if (direction == 1) { 
              id(control_bed_annick_head_up).execute();
              return;
            } else {
              id(control_bed_annick_head_down).execute();
              return;
            };
            case 2: if (direction == 1){ 
              id(control_bed_annick_feet_up).execute();
              return;
            } else {
              id(control_bed_annick_feet_down).execute();
              return;
            };
            case 3: if (direction == 1){ 
              id(control_bed_annick_both_up).execute();
              return;
            } else {
              id(control_bed_annick_both_down).execute();
              return;
            };
            default: {      
              id(control_bed_annick_stop_cmd).execute();
              return;
            }
          }
  - id: control_bed_peter
    mode: restart
    parameters:
      section: int #1 head, 2 feet, 3 both
      direction: int # 1 up, 0 down
      #percentage? voor later is nu op lager niceau opgelost
    then:
      - ble_client.ble_write: #send stop command
          id: rc2bedpeter
          service_uuid: ffe0
          characteristic_uuid: ffe1
          # List of bytes to write.
          value: [0x40, 0x02, 0x73, 0x00, 0x00, 0x0b, 0x40]
      # Check what task to perform
      - lambda: |-
          switch (section) {
            case 1: if (direction == 1) { 
              id(control_bed_peter_head_up).execute();
              return;
            } else {
              id(control_bed_peter_head_down).execute();
              return;
            };
            case 2: if (direction == 1){ 
              id(control_bed_peter_feet_up).execute();
              return;
            } else {
              id(control_bed_peter_feet_down).execute();
              return;
            };
            case 3: if (direction == 1){ 
              id(control_bed_peter_both_up).execute();
              return;
            } else {
              id(control_bed_peter_both_down).execute();
              return;
            };
            default: {      
              id(control_bed_peter_stop_cmd).execute();
              return;
            }
          }
  - id: control_bed_annick_head_up
    mode: single
    then:
      - script.stop: control_bed_annick_both_down
      - script.stop: control_bed_annick_both_up
      - script.stop: control_bed_annick_feet_down
      - script.stop: control_bed_annick_feet_up
      - script.stop: control_bed_annick_head_down
      #- script.stop: control_bed_annick_head_up
      - repeat:
          count: 30 #this is not fully up(!)
          then:
            - ble_client.ble_write:
                id: rc2bedannick
                service_uuid: ffe0
                characteristic_uuid: ffe1
                # List of bytes to write.
                value: [0x40, 0x02, 0x70, 0x00, 0x01, 0x0b, 0x02, 0x40]
            - delay: 300ms
            - logger.log: "repeat head UP Annick"
  - id: control_bed_peter_head_up
    mode: single
    then:
      - script.stop: control_bed_peter_both_down
      - script.stop: control_bed_peter_both_up
      - script.stop: control_bed_peter_feet_down
      - script.stop: control_bed_peter_feet_up
      - script.stop: control_bed_peter_head_down
      #- script.stop: control_bed_peter_head_up
      - repeat:
          count: 100 # 70 is typically enough
          then:
            - ble_client.ble_write:
                id: rc2bedpeter
                service_uuid: ffe0
                characteristic_uuid: ffe1
                # List of bytes to write.
                value: [0x40, 0x02, 0x70, 0x00, 0x01, 0x0b, 0x02, 0x40]
            - delay: 300ms
            - logger.log: "repeat head UP Peter"
  - id: control_bed_annick_head_down
    mode: single
    then:
      - script.stop: control_bed_annick_both_down
      - script.stop: control_bed_annick_both_up
      - script.stop: control_bed_annick_feet_down
      - script.stop: control_bed_annick_feet_up
      #- script.stop: control_bed_annick_head_down
      - script.stop: control_bed_annick_head_up
      - repeat:
          count: 100 # 70 is typically enough
          then:
            - ble_client.ble_write:
                id: rc2bedannick
                service_uuid: ffe0
                characteristic_uuid: ffe1
                # List of bytes to write.
                value: [0x40, 0x02, 0x71, 0x00, 0x01, 0x0a, 0x02, 0x40]
            - delay: 300ms
            - logger.log: "repeat head DOWN Annick"
  - id: control_bed_peter_head_down
    mode: single
    then:
      - script.stop: control_bed_peter_both_down
      - script.stop: control_bed_peter_both_up
      - script.stop: control_bed_peter_feet_down
      - script.stop: control_bed_peter_feet_up
      #- script.stop: control_bed_peter_head_down
      - script.stop: control_bed_peter_head_up
      - repeat:
          count: 100 # 70 is typically enough
          then:
            - ble_client.ble_write:
                id: rc2bedpeter
                service_uuid: ffe0
                characteristic_uuid: ffe1
                # List of bytes to write.
                value: [0x40, 0x02, 0x71, 0x00, 0x01, 0x0a, 0x02, 0x40]
            - delay: 300ms
            - logger.log: "repeat head DOWN Peter"
  - id: control_bed_annick_feet_up
    mode: single
    then:
      - script.stop: control_bed_annick_both_down
      - script.stop: control_bed_annick_both_up
      - script.stop: control_bed_annick_feet_down
      #- script.stop: control_bed_annick_feet_up
      - script.stop: control_bed_annick_head_down
      - script.stop: control_bed_annick_head_up
      - repeat:
          count: 100 # 40 is typically enough
          then:
            - ble_client.ble_write:
                id: rc2bedannick
                service_uuid: ffe0
                characteristic_uuid: ffe1
                # List of bytes to write.
                value: [0x40, 0x02, 0x70, 0x00, 0x01, 0x09, 0x04, 0x40]
            - delay: 300ms
            - logger.log: "repeat feet up Annick"
  - id: control_bed_peter_feet_up
    mode: single
    then:
      - script.stop: control_bed_peter_both_down
      - script.stop: control_bed_peter_both_up
      - script.stop: control_bed_peter_feet_down
      #- script.stop: control_bed_peter_feet_up
      - script.stop: control_bed_peter_head_down
      - script.stop: control_bed_peter_head_up
      - repeat:
          count: 100 # 40 is typically enough
          then:
            - ble_client.ble_write:
                id: rc2bedpeter
                service_uuid: ffe0
                characteristic_uuid: ffe1
                # List of bytes to write.
                value: [0x40, 0x02, 0x70, 0x00, 0x01, 0x09, 0x04, 0x40]
            - delay: 300ms
            - logger.log: "repeat feet up Peter"
  - id: control_bed_annick_feet_down
    mode: single
    then:
      - script.stop: control_bed_annick_both_down
      - script.stop: control_bed_annick_both_up
      #- script.stop: control_bed_annick_feet_down
      - script.stop: control_bed_annick_feet_up
      - script.stop: control_bed_annick_head_down
      - script.stop: control_bed_annick_head_up
      - repeat:
          count: 100 # 50 is typically enough
          then:
            - ble_client.ble_write:
                id: rc2bedannick
                service_uuid: ffe0
                characteristic_uuid: ffe1
                # List of bytes to write.
                value: [0x40, 0x02, 0x71, 0x00, 0x01, 0x08, 0x04, 0x40]
            - delay: 300ms
            - logger.log: "repeat feet down Annick"
  - id: control_bed_peter_feet_down
    mode: single
    then:
      - script.stop: control_bed_peter_both_down
      - script.stop: control_bed_peter_both_up
      #- script.stop: control_bed_peter_feet_down
      - script.stop: control_bed_peter_feet_up
      - script.stop: control_bed_peter_head_down
      - script.stop: control_bed_peter_head_up
      - repeat:
          count: 100 # 50 is typically enough
          then:
            - ble_client.ble_write:
                id: rc2bedpeter
                service_uuid: ffe0
                characteristic_uuid: ffe1
                # List of bytes to write.
                value: [0x40, 0x02, 0x71, 0x00, 0x01, 0x08, 0x04, 0x40]
            - delay: 300ms
            - logger.log: "repeat feet down Peter"
  - id: control_bed_annick_both_up
    mode: single
    then:
      - script.stop: control_bed_annick_both_down
      #- script.stop: control_bed_annick_both_up
      - script.stop: control_bed_annick_feet_down
      - script.stop: control_bed_annick_feet_up
      - script.stop: control_bed_annick_head_down
      - script.stop: control_bed_annick_head_up
      - repeat:
          count: 30
          then:
            - ble_client.ble_write:
                id: rc2bedannick
                service_uuid: ffe0
                characteristic_uuid: ffe1
                # List of bytes to write.
                value: [0x40, 0x02, 0x70, 0x00, 0x01, 0x07, 0x06, 0x40]
            - delay: 300ms
            - logger.log: "repeat both up Annick"
  - id: control_bed_peter_both_up
    mode: single
    then:
      - script.stop: control_bed_peter_both_down
      #- script.stop: control_bed_peter_both_up
      - script.stop: control_bed_peter_feet_down
      - script.stop: control_bed_peter_feet_up
      - script.stop: control_bed_peter_head_down
      - script.stop: control_bed_peter_head_up
      - repeat:
          count: 100 # 70 is typically enough
          then:
            - ble_client.ble_write:
                id: rc2bedpeter
                service_uuid: ffe0
                characteristic_uuid: ffe1
                # List of bytes to write.
                value: [0x40, 0x02, 0x70, 0x00, 0x01, 0x07, 0x06, 0x40]
            - delay: 300ms
            - logger.log: "repeat both up Peter"
  - id: control_bed_annick_both_down
    mode: single
    then:
      #- script.stop: control_bed_annick_both_down
      - script.stop: control_bed_annick_both_up
      - script.stop: control_bed_annick_feet_down
      - script.stop: control_bed_annick_feet_up
      - script.stop: control_bed_annick_head_down
      - script.stop: control_bed_annick_head_up
      - repeat:
          count: 100 # 70 is typically enough
          then:
            - ble_client.ble_write:
                id: rc2bedannick
                service_uuid: ffe0
                characteristic_uuid: ffe1
                # List of bytes to write.
                value: [0x40, 0x02, 0x71, 0x00, 0x01, 0x06, 0x06, 0x40]
            - delay: 300ms
            - logger.log: "repeat both down Annick"
  - id: control_bed_peter_both_down
    mode: single
    then:
      #- script.stop: control_bed_peter_both_down
      - script.stop: control_bed_peter_both_up
      - script.stop: control_bed_peter_feet_down
      - script.stop: control_bed_peter_feet_up
      - script.stop: control_bed_peter_head_down
      - script.stop: control_bed_peter_head_up
      - repeat:
          count: 100 # 70 is typically enough
          then:
            - ble_client.ble_write:
                id: rc2bedpeter
                service_uuid: ffe0
                characteristic_uuid: ffe1
                # List of bytes to write.
                value: [0x40, 0x02, 0x71, 0x00, 0x01, 0x06, 0x06, 0x40]
            - delay: 300ms
            - logger.log: "repeat both down Peter"
  - id: control_bed_annick_stop_cmd
    mode: single
    then:
      - script.stop: control_bed_annick_both_down
      - script.stop: control_bed_annick_both_up
      - script.stop: control_bed_annick_feet_down
      - script.stop: control_bed_annick_feet_up
      - script.stop: control_bed_annick_head_down
      - script.stop: control_bed_annick_head_up
  - id: control_bed_peter_stop_cmd
    mode: single
    then:
      - script.stop: control_bed_peter_both_down
      - script.stop: control_bed_peter_both_up
      - script.stop: control_bed_peter_feet_down
      - script.stop: control_bed_peter_feet_up
      - script.stop: control_bed_peter_head_down
      - script.stop: control_bed_peter_head_up
#      - ble_client.ble_write:
#          id: rc2bedpeter
#          service_uuid: ffe0
#          characteristic_uuid: ffe1
#          # List of bytes to write.
#          value: [0x40, 0x02, 0x73, 0x00, 0x00, 0x0b, 0x40]
1 Like

Thank you for sharing! I tested it (and only used one of the 2 beds :wink: )

The code acts the same. Here’s a snipped of my log:

[14:00:53][I][safe_mode:041]: Boot seems successful; resetting boot loop counter
[14:00:53][D][esp32.preferences:114]: Saving 1 preferences to flash...
[14:00:53][D][esp32.preferences:143]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failed
[14:00:53][D][main:239]: repeat head UP Annick
[14:00:53][D][esp32_ble_client:110]: [0] [F6:21:DD:DD:6F:19] ESP_GATTC_WRITE_CHAR_EVT
[14:00:53][D][main:239]: repeat head UP Annick
[14:00:54][D][esp32_ble_client:110]: [0] [F6:21:DD:DD:6F:19] ESP_GATTC_WRITE_CHAR_EVT
[14:00:54][D][main:239]: repeat head UP Annick
[14:00:54][D][esp32_ble_client:110]: [0] [F6:21:DD:DD:6F:19] ESP_GATTC_WRITE_CHAR_EVT
[14:00:54][D][main:239]: repeat head UP Annick
[14:00:54][D][esp32_ble_client:110]: [0] [F6:21:DD:DD:6F:19] ESP_GATTC_WRITE_CHAR_EVT
[14:00:55][D][main:239]: repeat head UP Annick
[14:00:55][D][esp32_ble_client:110]: [0] [F6:21:DD:DD:6F:19] ESP_GATTC_WRITE_CHAR_EVT
[14:00:55][D][main:239]: repeat head UP Annick
[14:00:55][D][esp32_ble_client:110]: [0] [F6:21:DD:DD:6F:19] ESP_GATTC_WRITE_CHAR_EVT

The light works but the commands don’t do anything

When I turn on the app and make a connection, the ESPHOME code works:

[14:17:56][I][esp32_ble_client:067]: [0] [F6:21:DD:DD:6F:19] 0x01 Attempting BLE connection
[14:17:57][D][esp32_ble_client:110]: [0] [F6:21:DD:DD:6F:19] ESP_GATTC_CONNECT_EVT
[14:17:57][D][esp32_ble_client:110]: [0] [F6:21:DD:DD:6F:19] ESP_GATTC_OPEN_EVT
[14:17:57][D][esp32_ble_tracker:270]: Starting scan...
[14:18:01][D][esp32_ble_client:306]: [0] [F6:21:DD:DD:6F:19] Event 46
[14:18:01][D][esp32_ble_client:110]: [0] [F6:21:DD:DD:6F:19] ESP_GATTC_SEARCH_CMPL_EVT
[14:18:01][I][esp32_ble_client:227]: [0] [F6:21:DD:DD:6F:19] Connected

Almost as if it just doesn’t (want) to connect before.

How do I force a connection?

The BLE scan results in a connection. B.t.w., In HA you should now also be able to see the connection state.

Logging seems all fine as far as I can conclude.

I think I have the Octobox Octo-Box - Octo (octo-actuators.de) (or maybe an older generation of this).

Possibly you have a different type of controller requiring different commands for the bed movement. Only way to know for sure is to log the bluetooth communication between the app on your phone and the bed itself to find out the actual commands sent. An instruction like this Bluetooth packet capture with Wireshark on Android | NowSecure can help

1 Like

I used PacketLogger, it does the same trick.

What I did is to see what happens when I open the octo app without sending commands myself.

It seems it’s sending some commands (see the values in the screenshot). I tried to reproduce within ESPHome by trying to automatically sending the same commands but I’m not getting a connection. Maybe someone else can crack this, I’m out of ideas.