AM43 blinds control through MQTT

I’m duble check and looks good, below config and logs:

esphome:
  name: esp
  platform: ESP32
  board: esp-wrover-kit
  on_boot:
    - script.execute: main1
    - script.wait: main1
#esphome:
#  name: ble

#esp32:
#  board: esp32dev
#  framework:
#   type: arduino



# Enable logging
logger:
#  level: VERY_VERBOSE

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

ota:
  password: "xxxxxxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  use_address: 192.168.1.107
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Ble Fallback Hotspot"
    password: "xxxxxxxxxxxxxxxx"

web_server:
  port: 80

captive_portal:
  
ble_client:

  - mac_address: 02:9E:88:EB:B5:F6
    id: bedroom_left_blind
    on_connect:
      - binary_sensor.template.publish:
          id: left_connected
          state: ON
      - logger.log: 
          format: "CONNECT LEFT"
          level: INFO
    on_disconnect:
      - binary_sensor.template.publish:
          id: left_connected
          state: OFF
      - logger.log: 
          format: "DISCONNECT LEFT"
          level: INFO
          

binary_sensor:

  - platform: template
    device_class: connectivity
    id: left_connected
    name: "Left connected"


  - platform: template
    device_class: opening
    id: left_open_status
    name: "Left status"

sensor:

  - platform: uptime
    name: Uptime Sensor

  
  - platform: ble_rssi
    id: bedroom_left_blind_rssi
    mac_address: 02:9E:88:EB:B5:F6
    name: "Bedroom Left Blind RSSI"


  - platform: am43
    ble_client_id: bedroom_left_blind
    illuminance:
      name: "Bedroom Left Blind Light"
      filters:
        - filter_out: nan
    battery_level:
      name: "Bedroom Left Blind Battery"
      filters:
        - filter_out: nan
    update_interval: 30sec
    

switch:

  - platform: restart
    name: "Bedroom Blind ESP Reboot"
    
  - platform: ble_client
    name: "Bedroom Left Blind BLE"
    id: bedroom_left_blind_ble
    ble_client_id: bedroom_left_blind
      

cover:
  
  - platform: am43
    id: bedroom_left_blind_cover_internal
    ble_client_id: bedroom_left_blind
    pin: 8888
    internal: true
    on_open:
      - binary_sensor.template.publish:
          id: left_open_status
          state: ON
    on_closed:
      - binary_sensor.template.publish:
          id: left_open_status
          state: OFF

    
  - platform: template
    name: "Bedroom Blinds"
    id: bedroom_blinds_cover
    has_position: true
    lambda: |-
      return (id(bedroom_left_blind_cover_internal).position);
    open_action:
      then:
        - script.execute: open_action
    close_action:
      then:
        - script.execute: close_action
    stop_action:
      then:
        - script.execute: stop_action
    position_action:
      then:
        - script.execute: 
            id: position_action
            value: !lambda return pos;

script:

  - id: open_action
    mode: restart
    then:
      - script.stop: close_action
      - script.stop: stop_action
      - script.stop: position_action
      - script.stop: update_sensors
      - logger.log: 
          format: "Open ..."
          level: INFO
      - script.execute: enable_ble
      - script.wait: enable_ble
      - cover.open: bedroom_left_blind_cover_internal
      - while:
          condition:
            not:
              and:
                - binary_sensor.is_on: left_open_status
          then:
            - logger.log: 
                format: "... opening ..."
                level: INFO
            - delay: 1sec
      - logger.log: 
          format: "... opened"
          level: INFO
      - script.execute: update_sensors
    
  - id: close_action
    mode: restart
    then:
      - script.stop: open_action
      - script.stop: stop_action
      - script.stop: position_action
      - script.stop: update_sensors
      - logger.log: 
          format: "Close ..."
          level: INFO
      - script.execute: enable_ble
      - script.wait: enable_ble
      - cover.close: bedroom_left_blind_cover_internal
      - while:
          condition:
            not:
              and:
                - binary_sensor.is_off: left_open_status
          then:
            - logger.log: 
                format: "... closing ..."
                level: INFO
            - delay: 1sec
      - logger.log: 
          format: "... closed"
          level: INFO
      - script.execute: update_sensors
    
  - id: stop_action
    mode: restart
    then:
      - script.stop: open_action
      - script.stop: close_action
      - script.stop: position_action
      - script.stop: update_sensors
      - logger.log: 
          format: "Stop ..."
          level: INFO
      - script.execute: enable_ble
      - script.wait: enable_ble
      - cover.stop: bedroom_left_blind_cover_internal
      - logger.log: 
          format: "... stoped"
          level: INFO
      - script.execute: update_sensors
    
  - id: position_action
    mode: restart
    parameters:
      value: float
    then:
      - script.stop: open_action
      - script.stop: close_action
      - script.stop: stop_action
      - script.stop: update_sensors
      - logger.log: 
          format: "Set position %f ..."
          level: INFO
          args: [ value ]
      - script.execute: enable_ble
      - script.wait: enable_ble
      - cover.control:
          id: bedroom_left_blind_cover_internal
          position: !lambda return value;
      - script.execute: update_sensors
    
  - id: enable_ble
    mode: restart
    then:
      - script.stop: disable_ble
      - logger.log: 
          format: "Enabling BLE..."
          level: INFO
      - if:
          condition:
            - switch.is_off: bedroom_left_blind_ble
          then:
            - switch.turn_on: bedroom_left_blind_ble
      - while:
          condition:
            not:
              and:
                - binary_sensor.is_on: left_connected
          then:
            - logger.log: 
                format: "... waiting connection ..."
                level: INFO
            - delay: 1sec
      - logger.log: 
          format: "...BLE enabled"
          level: INFO

  - id: disable_ble
    mode: single
    then:
      - logger.log: 
          format: "Disabling BLE ..."
          level: INFO
      - switch.turn_off: bedroom_left_blind_ble
      - logger.log: 
          format: "... BLE disabled"
          level: INFO

  - id: update_sensors
    mode: single
    then:
      - logger.log: 
          format: "Updating sensor ..."
          level: INFO
      - script.execute: enable_ble
      - script.wait: enable_ble
      - delay: 1min
      - while: 
          condition:
            or:
              - script.is_running: open_action
              - script.is_running: close_action
              - script.is_running: stop_action
              - script.is_running: position_action
          then:
            - logger.log: 
                format: "... domething Still executing ..."
                level: INFO
            - delay: 10s
      - script.execute: disable_ble
      - script.wait: disable_ble
      - logger.log: 
          format: "... sensors updated"
          level: INFO

  - id: main1
    mode: single
    then:
      - while:
          condition:
            - lambda: "return true;"
          then:
            - script.execute: update_sensors
            - script.wait: update_sensors
            - delay: 60min
INFO Reading configuration /config/esp.yaml...
INFO Starting log output from 192.168.1.107 using esphome API
INFO Successfully connected to 192.168.1.107
[09:35:53][I][app:102]: ESPHome version 2022.12.3 compiled on Jan 16 2023, 22:43:45
[09:35:53][C][wifi:504]: WiFi:
[09:35:53][C][wifi:362]:   Local MAC: CC:DB:A7:02:4E:5C
[09:35:53][C][wifi:363]:   SSID: [redacted]
[09:35:53][C][wifi:364]:   IP Address: 192.168.1.107
[09:35:53][C][wifi:366]:   BSSID: [redacted]
[09:35:54][C][wifi:367]:   Hostname: 'esp'
[09:35:55][C][ble_rssi:011]: BLE RSSI Sensor 'Bedroom Left Blind RSSI'
[09:35:57][I][main:264]: ... waiting connection ...
[09:35:57][I][main:264]: ... waiting connection ...
[09:35:58][I][main:264]: ... waiting connection ...
[09:35:59][I][main:264]: ... waiting connection ...
[09:36:00][I][main:264]: ... waiting connection ...
[09:36:01][I][main:264]: ... waiting connection ...
[09:36:02][I][main:264]: ... waiting connection ...
[09:36:03][I][main:264]: ... waiting connection ...
[09:36:04][I][main:264]: ... waiting connection ...
[09:36:05][I][main:264]: ... waiting connection ...
[09:36:06][I][main:264]: ... waiting connection ...
[09:36:07][I][main:264]: ... waiting connection ...
[09:36:08][I][main:264]: ... waiting connection ...
[09:36:09][I][main:264]: ... waiting connection ...
[09:36:10][I][main:264]: ... waiting connection ...
[09:36:11][I][main:264]: ... waiting connection ...
[09:36:12][I][main:264]: ... waiting connection ...
[09:36:13][I][main:264]: ... waiting connection ...
[09:36:14][I][main:264]: ... waiting connection ...
[09:36:15][I][main:264]: ... waiting connection ...
[09:36:16][I][main:264]: ... waiting connection ...
[09:36:17][I][main:264]: ... waiting connection ...
[09:36:18][I][main:264]: ... waiting connection ...
[09:36:19][I][main:264]: ... waiting connection ...
[09:36:20][I][main:264]: ... waiting connection ...
[09:36:21][I][main:264]: ... waiting connection ...
[09:36:22][I][main:264]: ... waiting connection ...
[09:36:23][I][main:264]: ... waiting connection ...
[09:36:24][I][main:264]: ... waiting connection ...
[09:36:25][W][am43:098]: [02:9E:88:EB:B5:F6] Cannot poll, not connected
[09:36:25][I][main:264]: ... waiting connection ...
[09:36:26][I][main:264]: ... waiting connection ...

Not sure , but guess that and is redundant here because you are using single am43. Could you try with

      - while:
          condition:
            not:
              binary_sensor.is_on: left_connected

Аддон работал замечательно, но теперь я получаю ошибку: “s6-overlay-suexec: fatal: can only run as pid 1” Есть идеи?

Для HASIO.

I created a bluetooth proxy in the hope of connecting to my AM43 blinds (Blind Engine app).
They did not get discovered, my toothbrush on the other hand did so that confirmed that my board works and the bluetooth proxy does work.
I saw your code for the blinds and thought i could copy that.
Was i wrong do i need to do something else?
Do i need to remove the code for bluetooth proxy?
Did i mess up some renaming?

The error i get is the following:

Below is my code

esphome:
  name: blt-proxy
  friendly_name: blt-proxy
  on_boot:
    - script.execute: main
    - script.wait: main

esp32:
  board: esp32dev
  framework:
    type: arduino


# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "*redacted*"

ota:
  password: "*redacted*"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "blt-proxy"
    password: "*redacted*"

captive_portal:
    
esp32_ble_tracker:
  scan_parameters:
    interval: 1100ms
    window: 1100ms
    active: true

bluetooth_proxy:
  active: true

# Badkamer 02:49:52:55:0F:E0
# Dressing 02:B2:6C:27:74:6C

ble_client:

  - mac_address: 02:49:52:55:0F:E0
    id: badkamer_blind
    on_connect:
      - binary_sensor.template.publish:
          id: left_connected
          state: ON
      - logger.log: 
          format: "CONNECT LEFT"
          level: INFO
    on_disconnect:
      - binary_sensor.template.publish:
          id: left_connected
          state: OFF
      - logger.log: 
          format: "DISCONNECT LEFT"
          level: INFO
          
  - mac_address: 02:B2:6C:27:74:6C
    id: dressing_blind
    on_connect:
      - binary_sensor.template.publish:
          id: right_connected
          state: ON
      - logger.log: 
          format: "CONNECT RIGHT"
          level: INFO
    on_disconnect:
      - binary_sensor.template.publish:
          id: right_connected
          state: OFF
      - logger.log: 
          format: "DISCONNECT RIGHT"
          level: INFO

binary_sensor:

  - platform: template
    device_class: connectivity
    id: left_connected
    name: "Left connected"

  - platform: template
    device_class: connectivity
    id: right_connected
    name: "Right connected"

  - platform: template
    device_class: opening
    id: left_open_status
    name: "Left status"

  - platform: template
    device_class: opening
    id: right_open_status
    name: "Right status"

sensor:

  - platform: uptime
    name: Uptime Sensor

  # - platform: ble_client
  #   id: badkamer_blind_rssi
  #   type: rssi
  #   ble_client_id: badkamer_blind
  #   name: "Badkamer Blind RSSI"

  # - platform: ble_client
  #   id: dressing_blind_rssi
  #   type: rssi
  #   ble_client_id: dressing_blind
  #   name: "Dressing Blind RSSI"
  
  - platform: ble_rssi
    id: badkamer_blind_rssi
    mac_address: 02:7B:F1:3A:C6:63
    name: "Badkamer Blind RSSI"

  - platform: ble_rssi
    id: dressing_blind_rssi
    mac_address: 02:BD:67:49:4B:0D
    name: "Dressing Blind RSSI"

  - platform: am43
    ble_client_id: badkamer_blind
    illuminance:
      name: "Badkamer Blind Light"
      filters:
        - filter_out: nan
    battery_level:
      name: "Badkamer Blind Battery"
      filters:
        - filter_out: nan
    update_interval: 30sec
    
  - platform: am43
    ble_client_id: dressing_blind
    illuminance:
      name: "Dressing Blind Light"
      filters:
        - filter_out: nan
    battery_level:
      name: "Dressing Blind Battery"
      filters:
        - filter_out: nan
    update_interval: 30sec

switch:

  - platform: restart
    name: "Blind ESP Reboot"
    
  - platform: ble_client
    name: "Badkamer Blind BLE"
    id: badkamer_blind_ble
    ble_client_id: badkamer_blind
      
  - platform: ble_client
    name: "Dressing Blind BLE"
    id: dressing_blind_ble
    ble_client_id: dressing_blind

cover:
  
  - platform: am43
    id: badkamer_blind_cover_internal
    ble_client_id: badkamer_blind
    pin: 1234
    internal: true
    on_open:
      - binary_sensor.template.publish:
          id: left_open_status
          state: ON
    on_closed:
      - binary_sensor.template.publish:
          id: left_open_status
          state: OFF

  - platform: am43
    id: dressing_blind_cover_internal
    ble_client_id: dressing_blind
    pin: 1234
    internal: true
    on_open:
      - binary_sensor.template.publish:
          id: right_open_status
          state: ON
    on_closed:
      - binary_sensor.template.publish:
          id: right_open_status
          state: OFF
    
  - platform: template
    name: "Blinds"
    id: blinds_cover
    has_position: true
    lambda: |-
      return (id(badkamer_blind_cover_internal).position + id(dressing_blind_cover_internal).position) / 2;
    open_action:
      then:
        - script.execute: open_action
    close_action:
      then:
        - script.execute: close_action
    stop_action:
      then:
        - script.execute: stop_action
    position_action:
      then:
        - script.execute: 
            id: position_action
            value: !lambda return pos;

script:

  - id: open_action
    mode: restart
    then:
      - script.stop: close_action
      - script.stop: stop_action
      - script.stop: position_action
      - script.stop: update_sensors
      - logger.log: 
          format: "Open ..."
          level: INFO
      - script.execute: enable_ble
      - script.wait: enable_ble
      - cover.open: badkamer_blind_cover_internal
      - cover.open: dressing_blind_cover_internal
      - while:
          condition:
            not:
              and:
                - binary_sensor.is_on: left_open_status
                - binary_sensor.is_on: right_open_status
          then:
            - logger.log: 
                format: "... opening ..."
                level: INFO
            - delay: 1sec
      - logger.log: 
          format: "... opened"
          level: INFO
      - script.execute: update_sensors
    
  - id: close_action
    mode: restart
    then:
      - script.stop: open_action
      - script.stop: stop_action
      - script.stop: position_action
      - script.stop: update_sensors
      - logger.log: 
          format: "Close ..."
          level: INFO
      - script.execute: enable_ble
      - script.wait: enable_ble
      - cover.close: badkamer_blind_cover_internal
      - cover.close: dressing_blind_cover_internal
      - while:
          condition:
            not:
              and:
                - binary_sensor.is_off: left_open_status
                - binary_sensor.is_off: right_open_status
          then:
            - logger.log: 
                format: "... closing ..."
                level: INFO
            - delay: 1sec
      - logger.log: 
          format: "... closed"
          level: INFO
      - script.execute: update_sensors
    
  - id: stop_action
    mode: restart
    then:
      - script.stop: open_action
      - script.stop: close_action
      - script.stop: position_action
      - script.stop: update_sensors
      - logger.log: 
          format: "Stop ..."
          level: INFO
      - script.execute: enable_ble
      - script.wait: enable_ble
      - cover.stop: badkamer_blind_cover_internal
      - cover.stop: dressing_blind_cover_internal
      - logger.log: 
          format: "... stoped"
          level: INFO
      - script.execute: update_sensors
    
  - id: position_action
    mode: restart
    parameters:
      value: float
    then:
      - script.stop: open_action
      - script.stop: close_action
      - script.stop: stop_action
      - script.stop: update_sensors
      - logger.log: 
          format: "Set position %f ..."
          level: INFO
          args: [ value ]
      - script.execute: enable_ble
      - script.wait: enable_ble
      - cover.control:
          id: badkamer_blind_cover_internal
          position: !lambda return value;
      - cover.control:
          id: dressing_blind_cover_internal
          position: !lambda return value;
      - script.execute: update_sensors
    
  - id: enable_ble
    mode: restart
    then:
      - script.stop: disable_ble
      - logger.log: 
          format: "Enabling BLE..."
          level: INFO
      - if:
          condition:
            - switch.is_off: badkamer_blind_ble
          then:
            - switch.turn_on: badkamer_blind_ble
      - if:
          condition:
            - switch.is_off: dressing_blind_ble
          then:
            - switch.turn_on: dressing_blind_ble
      - while:
          condition:
            not:
              and:
                - binary_sensor.is_on: left_connected
                - binary_sensor.is_on: right_connected
          then:
            - logger.log: 
                format: "... waiting connection ..."
                level: INFO
            - delay: 1sec
      - logger.log: 
          format: "...BLE enabled"
          level: INFO

  - id: disable_ble
    mode: single
    then:
      - logger.log: 
          format: "Disabling BLE ..."
          level: INFO
      - switch.turn_off: badkamer_blind_ble
      - switch.turn_off: dressing_blind_ble
      - logger.log: 
          format: "... BLE disabled"
          level: INFO

  - id: update_sensors
    mode: single
    then:
      - logger.log: 
          format: "Updating sensor ..."
          level: INFO
      - script.execute: enable_ble
      - script.wait: enable_ble
      - delay: 1min
      - while: 
          condition:
            or:
              - script.is_running: open_action
              - script.is_running: close_action
              - script.is_running: stop_action
              - script.is_running: position_action
          then:
            - logger.log: 
                format: "... domething Still executing ..."
                level: INFO
            - delay: 10s
      - script.execute: disable_ble
      - script.wait: disable_ble
      - logger.log: 
          format: "... sensors updated"
          level: INFO

  - id: main
    mode: single
    then:
      - while:
          condition:
            - lambda: "return true;"
          then:
            - script.execute: update_sensors
            - script.wait: update_sensors
            - delay: 60min

Why have you renamed the main_loop script to main? main is reserved, so just return it back)

Thank you for your reply!
I was under the impression that this must be named ‘main’
because it was in the example code :blush:

Or am i looking at an older version of the code?

I’ll try to change this ASAP and get back to you!

Hm, i’ve only compared a local version with your and found that discrepancy. I don’t remember that i did it by myself, maybe it was updated by some ESPHome update. Who knows…

No problem, i got it installed, stupid mistake… I am not too familiar with esphome…

I used the bluetooth mac addresses but they won’t connect, do i need to disconnect the AM43 blinds from the Blind engine on my phone or do i need to keep it open while connecting?

Yeah, coding on yaml blows a mind. I would to make configurable by operating with list or array of drivers, but it does not look to be feasible for now.
ESP connects to am43 via bluetooth on demand only to perform user’s action, or to refresh sensor periodically (battery, light, etc.). So, am43 must be disconnected from phones.
This script useful for automation/scenario of am43 because it saves battery, but it not comfortable for direct binding to wall switch/button, since it requires some time to negotiate Bluetooth connection to send command

ok, i’ll try to remove it from the app and hopefully get it connected.
Do i need to reconfigure it then or will it keep the settings set through the Blinds engine app?
i don’t need a direct binding but i would like to automatically let it close when i detect x amount of lumen or when it’s this time or something like that? Or is that not possible with this code / devices?

Do i need to reconfigure it then or will it keep the settings set through the Blinds engine app?

You don’t need to reconfigure top/bottom point, speed setting, etc. But scheduling in Blinds engine should be disabled.

i don’t need a direct binding but i would like to automatically let it close when i detect x amount of lumen or when it’s this time or something like that? Or is that not possible with this code / devices?

This exactly purpose of usage for this script. I have an automation which opens blindы every non-holiday morning at time from input_datetime.open_blinds_working_day helper AND closes after sunset

alias: Control blinds
description: Open/close blind by trigger
trigger:
  - platform: time
    at: input_datetime.open_blinds_working_day
    id: open
  - platform: numeric_state
    entity_id: sun.sun
    attribute: elevation
    below: -3
    id: close
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: open
          - condition: state
            entity_id: binary_sensor.workday_sensor
            state: "on"
        sequence:
          - service: cover.open_cover
            data: {}
            target:
              entity_id: cover.bedroom_blinds
      - conditions:
          - condition: trigger
            id: close
        sequence:
          - service: cover.close_cover
            data: {}
            target:
              entity_id: cover.bedroom_blinds
    default:
      - if:
          - condition: sun
            before: sunrise
            after: sunset
        then:
          - service: cover.close_cover
            data: {}
            target:
              entity_id: cover.bedroom_blinds
mode: single

Still not able to connect them, even after removing them from the app…
they don’t get discovered either like my Oral-B.
Any thoughts?

I’ve been struggling to establish a connection with the AM43 for what feels like ages, completely clueless about what was causing the issue. While going through this thread, I stumbled upon a suggestion to try a different board, which I initially overlooked. The board I had been using was my BT proxy, which works perfectly for everything except the AM43. It was a combination of all the problems mentioned here, and none of them seemed to get resolved until I made the switch to the ESP32.

Now, I’ve successfully connected the AM43 to my ESP32-WROOM-32UE with an external antenna. The previous board could detect the AM43 by its name from the Smart Blinds APP, but establishing a connection was a no-go. So, to anyone else grappling with a similar issue, my advice would be to experiment with as many ESP32 boards as possible until you find one that works.
@LiveDrunk , @spyro-po

1 Like

Could you point me in the right direction on which device you use now?
ESP32-WROOM-32UE with an external antenna, perhaps a link?

Was able to connect and open and close them! Great success.
Now only i see a massive battery drain (40% gone in a day)
Might need to try the confige from above if i can keep the connection.

The connection is up on demand to avoid battery draining, so make sure the ble switch and binary sensor in appropriate states. In other words, esp should connect to am43 only after get a command (open/close/set position) from HA initiated by user or automation, and after the command is executed esp should terminate BLE connection with am43. Periodically esp connects to am43 by it self to update battery/light sensors

Thank you very much, this worked for me perfectly!! This save me a lot of work and the implementation is nice.

Guess it is grow enough to have own repo)

1 Like

I renamed main, to main_am43 (or main_loop) to make it work