esphome / feature-requests

ESPHome Feature Request Tracker
https://esphome.io/
406 stars 26 forks source link

I need Help to use esp32 to Control Yeelight Candla BLE Lamp with MQTT / HomeAssisant #674

Open Titanius opened 4 years ago

Titanius commented 4 years ago

to the best programmers - it is possible to do this with an ESP32

Use a esp32 to Control Yeelight Candela BLE Lamp. On / Off / brightness

Links i found: https://github.com/praschak/candelapy https://github.com/rytilahti/python-yeelightbt

paki111 commented 2 years ago

I have my Candela in HomeAssistant, but the connection isn't stable. I just thought as you, to use esp32... I'm using ESPHome ble hub to read Mi sensors, maybe it is possible to connect Yeelight Candela similiar to Yeelight night lamp?

MiguelAngelLV commented 2 years ago

I have the same problem. I have a ESP32 to read my xiaomi temperature sensor and I want use it to control the candela too.

nagyrobi commented 2 years ago

Please see https://github.com/dentra/esphome-components/tree/master/components/miot_ylai003, does this work for you? Possibly related to https://github.com/esphome/feature-requests/issues/1230

MiguelAngelLV commented 2 years ago

@nagyrobi that is BLE remote control. We need that esp32 control the light, not control the esp32 with the light.

0x5e commented 1 year ago

Here's some informations about OpenMQTTGateway control the Yeelight BLE Candela: https://community.openmqttgateway.com/t/feature-request-support-for-xiaomi-yeelight-ble-candela/1898/1

I have exactly the same requirements with @MiguelAngelLV , I have a Mi sensor and a Yeelight Candela :)

0x5e commented 1 year ago

I have some experiment and on/off is supported now, here's my config:

ble_client:
  - mac_address: XX:XX:XX:XX:XX:XX
    id: yeelight_ms
    on_connect:
      then:
        - script.execute: yeelight_pair

switch:
  - platform: template
    id: yeelight_candela
    name: "Yeelight Candela"
    turn_on_action:
      - script.execute: yeelight_on
    turn_off_action:
      - script.execute: yeelight_off

script:
  - id: yeelight_on
    then:
      - ble_client.ble_write:
          id: yeelight_ms
          service_uuid: FE87
          characteristic_uuid: AA7D3F34-2D4F-41E0-807F-52FBF8CF7443
          value: [0x43, 0x40, 0x01]
  - id: yeelight_off
    then:
      - ble_client.ble_write:
          id: yeelight_ms
          service_uuid: FE87
          characteristic_uuid: AA7D3F34-2D4F-41E0-807F-52FBF8CF7443
          value: [0x43, 0x40, 0x02]
  - id: yeelight_pair
    then:
      - delay: 3s
      - script.execute: yeelight_off
      - delay: 0.5s
      - script.execute: yeelight_on
      - delay: 0.5s
      - ble_client.ble_write:
          id: yeelight_ms
          service_uuid: FE87
          characteristic_uuid: AA7D3F34-2D4F-41E0-807F-52FBF8CF7443
          value: [0x43, 0x67, 0x02] # enable pulse mode

Without the pairing process, the ble connection will be disconnected by candela every 30s, then the on/off command will have to connect at first everytime, the whole process cost about 2s.

The config above solved the pairing issue, the long connection keep the trigger command in low lagency.

Need to upload config twice. First time keep - script.execute: yeelight_pair this line, when candela connected, it will came into pair mode, rotate the candela to complete the pair process. Second time, remove - script.execute: yeelight_pair, and upload again.

The brightness command is [0x43, 0x42, 0x00~0xFF], I'm not very familiar with esphome config, if anyone knows how, please let me know :)

0x5e commented 6 months ago

Update config:

substitutions:
  YEELIGHT_STATUS_LED_PIN: LED1_BUILTIN
  YEELIGHT_PAIR_BUTTON_PIN: GPIO09

  YEELIGHT_SERVICE_UUID: FE87
  YEELIGHT_NOTIFY_UUID: 8F65073D-9F57-4AAA-AFEA-397D19D5BBEB
  YEELIGHT_CONTROL_UUID: AA7D3F34-2D4F-41E0-807F-52FBF8CF7443
  YEELIGHT_MAC: XX:XX:XX:XX:XX:XX

esphome:
  name: ble-over-mqtt
  platformio_options:
    board_build.flash_mode: dio

esp32:
  board: airm2m_core_esp32c3
  framework:
    type: arduino

logger:
  baud_rate: 921600

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

mqtt:
  broker: x.x.x.x
  port: 1883
  username: xxx
  password: xxx
  on_json_message:
    - topic: ble-over-mqtt/command/yeelight_power
      then:
        - lambda: |-
            x["power"] ? id(output_yeelight_power).turn_on() : id(output_yeelight_power).turn_off();
    - topic: ble-over-mqtt/command/yeelight_brightness
      then:
        - lambda: |-
            id(output_yeelight_brightness).set_level((int)(x["brightness"]) / 100.0);

esp32_ble_tracker:

ble_client:
  - mac_address: $YEELIGHT_MAC
    id: ble_yeelight
    on_connect:
      - binary_sensor.template.publish:
          id: binary_sensor_yeelight_presence
          state: ON
      - output.turn_on: output_yeelight_presence
    on_disconnect:
      - binary_sensor.template.publish:
          id: binary_sensor_yeelight_presence
          state: OFF
      - output.turn_off: output_yeelight_presence

binary_sensor:
  - platform: template
    id: binary_sensor_yeelight_presence
    name: "Yeelight Presence"
  - platform: template
    id: binary_sensor_yeelight_power
    name: "Yeelight Power"
  - platform: gpio
    id: binary_sensor_yeelight_pair
    name: "Yeelight Pair Button"
    pin:
      number: $YEELIGHT_PAIR_BUTTON_PIN
      inverted: true
    on_click:
      - button.press: button_yeelight_pair

sensor:
  - platform: ble_client
    type: characteristic
    ble_client_id: ble_yeelight
    id: sensor_yeelight
    internal: true
    service_uuid: $YEELIGHT_SERVICE_UUID
    characteristic_uuid: $YEELIGHT_NOTIFY_UUID
    lambda: |-
      ESP_LOGD("main", "Received yeelight status notify: %s", format_hex(x).c_str());
      if (x.size() > 4 && x[0] == 0x43 && x[1] == 0x45) {
        bool power = (x[2] == 0x01);
        float brightness = x[3] / 100.0;

        ESP_LOGD("main", "Power: %s", power ? "On" : "Off");
        ESP_LOGD("main", "Brightness: %.2f", brightness);

        id(binary_sensor_yeelight_power).publish_state(power);
        id(sensor_yeelight_brightness).publish_state(brightness);
      }
      return {};
    notify: true
  - platform: template
    id: sensor_yeelight_brightness
    name: "Yeelight Brightness"
    accuracy_decimals: 2

output:
  - platform: gpio
    pin: $YEELIGHT_STATUS_LED_PIN
    id: output_yeelight_presence
  - platform: template
    id: output_yeelight_power
    type: binary
    write_action:
      - ble_client.ble_write:
          id: ble_yeelight
          service_uuid: $YEELIGHT_SERVICE_UUID
          characteristic_uuid: $YEELIGHT_CONTROL_UUID
          value: !lambda 'return { 0x43, 0x40, (char)(state ? 0x01 : 0x02) };'
  - platform: template
    id: output_yeelight_brightness
    type: float
    write_action:
      - ble_client.ble_write:
          id: ble_yeelight
          service_uuid: $YEELIGHT_SERVICE_UUID
          characteristic_uuid: $YEELIGHT_CONTROL_UUID
          value: !lambda 'return { 0x43, 0x42, (char)(state * 0x64) };'

button:
  - platform: template
    id: button_yeelight_pair
    on_press:
      - output.turn_off: output_yeelight_power
      - output.turn_on: output_yeelight_power
      - ble_client.ble_write:
          id: ble_yeelight
          service_uuid: $YEELIGHT_SERVICE_UUID
          characteristic_uuid: $YEELIGHT_CONTROL_UUID
          value: [0x43, 0x67, 0x02] # enable pulse mode

quite complicated, but it works for me, with status update notify.

hope someone can combine it to a single c++ component.