Controlling BLE ceiling light with HA

Ok, the results of your last code change:

Color Temperatures: Correct (ish), my light can get a lot Yellower / whiter with the remote
Brightness: If the value is above 50% or so, the temperature can still change, below the 50% value, the color temperature stays the same, so i’m not able to dim to a warmer color.

Question: Is it possible to retrieve/see the state the light is in when controlling it with the app or the remote? This way i might be able to see what my maximum and minimum values are.

Color Temperatures: Correct (ish), my light can get a lot Yellower / whiter with the remote

Can you try setting the cold_white_color_temperature and warm_white_color_temperature configuration options for the light? I haven’t documented it (will do), and it defaults to the values supported by my light - but the values are configurable. See here for an example: Cold White + Warm White Light — ESPHome

Brightness: If the value is above 50% or so, the temperature can still change, below the 50% value, the color temperature stays the same, so i’m not able to dim to a warmer color.

Interesting. Not sure what the issue might be… I suggest we resolve the temperatures correctly (see above), before we tackle this issue.

Question: Is it possible to retrieve/see the state the light is in when controlling it with the app or the remote? This way i might be able to see what my maximum and minimum values are.

Not currently, and I haven’t explored the possibility. I’ll have to see whether the lamp broadcasts any packets that I can catch. You could try recording the packets from the remote - though my code is not using packets compatible with the remote, so not sure I’ll be able to understand that data. How about controlling the light with the LampSmart Pro app - does that work correctly? Do you get the same range of temperature/brightness as with the remote?

I can’t set the brightness or the color as low as the remote with the app.

After setting the white values, things changed!
with the current settings:

light:
  - platform: lampsmart_pro_light
    name: Slaapkamer Lamp
    duration: 1000
    default_transition_length: 0s
    cold_white_color_temperature: 7000 K
    warm_white_color_temperature: 1800 K

and the following brightness levels:

  uint8_t cwi = 0x01 + (uint8_t)((0xff - 0x01) * cwf);
  uint8_t wwi = 0x01 + (uint8_t)((0xff - 0x01) * wwf);

The device dimms nicely yellowish like i’d like to.
However, like you stated, the values are to low.
When setting the values (in the brightness) to 0x01, Home Assistant is sending these values:

11:29:46	[D]	[lampsmartpro:119]	
LampSmartProLight::write_state called! Requested cw: 1, ww: 7
11:29:48	[D]	[light:035]	
'Slaapkamer Lamp' Setting:
11:29:48	[D]	[light:050]	
  Brightness: 22%
11:29:48	[D]	[light:050]	
  Brightness: 22%

So at 22% (warm white) the WW value is only 7, which results in 19% being just 3 and turning the light off.

If it’s 0x1A however, the CW value stays 26 the whole time, making the warm white a little to cold.

I’ll try changing the min_brightness Value and seeing what’ll happen.

EDIT:
changing the min_brightness value to 0xa kept the light on when dimming below 20%, however, when setting the light to warm white, the cold white value should be just off (not staying at around 10). If it stays at 10, when dimming the light, the cold white stays visible and thus making the light not as yellow as it should be.

I can’t set the brightness or the color as low as the remote with the app.

That means this might be a limiting factor - i.e., we might not reach the values possible with a remote, since we’re using the protocol used by the app… But maybe if we adjust the values correctly, it’ll work.

If it’s 0x1A however, the CW value stays 26 the whole time, making the warm white a little to cold.

I see now the problem with my code… There’s no reason for the minimum brightness to be applied to both the cold and warm values. I will push a fix soon (and edit this post when it’s done).

Also note that you don’t have to change the minimum brightness at the cwi and wwi values manually in code - you can just use the min_brightness configuration in YAML, and it should sort it out.

thanks! i tought the same, just didn’t know how to fix it fast :wink:

Could you give an example of the Yaml Code? (with the Min_brightness added)

Done, please check the latest version of the code :slight_smile:

Fixed the minimum brightness logic, now the temperature will be correct at lowest brightness settings (though, of course, at minimum brightness, the temperature resolution is rather abysmal - it’s either warm, cold, or both - nothing in-between).

Regarding a sample YAML - here you go:

# Enable LightSmart Pro Light
light:
  - platform: lampsmart_pro_light
    name: Kitchen Light
    duration: 1000
    default_transition_length: 0s
    min_brightness: 0x7

But you don’t need that any longer - I’ve updated the default value for minimum brightness to 7, it seems to work well. 0x1a (and 0x10) were definitely too high.

1 Like

Worked like a charm.
didn’t add the brightness part,
changed the wwi - cwi part in the code, but i guess this can be changed by adding:

light:
  - platform: lampsmart_pro_light
    name: Kitchen Light
    duration: 1000
    default_transition_length: 0s
    reversed: true

Thanks for the quick updates and the awesome work!!

No problem - glad to hear it worked! And yeah, reversed: true should take care of it and allow you to use the code as-is, without changes.

@aronsky I am so happy you got something going. :+1: I have 3 lights…are we saying I can only add 1 light or I can add 3 but will control them all with the same values? I tried putting the code into a DualR3 yesterday but getting some errors while compiling. Will setup another ESP32 only for this later to test.

Not sure what’s a DualR3… I’ve only tested this on a regular ESP32. Is the DualR3 based on ESP32? Dose it have BLE?

Regarding multiple lights - yeah, if you have multiple lights - they will all appear as a single light, as far as ESPHome and Home Assistant are concerned. It should be possible to differentiate in the future, but I need help with that in terms of implementing it correctly on the ESPHome side (I think I have a pretty good idea regarding how it should work on the lights side, but it requires some testing).

  [reversed] is an invalid option for [light.lampsmart_pro_light]. Please check the indentation.
  reversed: True

Sadly no luck. → got it working after a few tries
Will keep my local version running

Multiple lights would be awesome, if I can help out with testing let me know!
Would help to know the BLE Mac address of the device it’s connected to, is it possible to add this as a sensor? (or see it in the logs)

Sadly no luck.
Will keep my local version running

Strange, it works for me… Any chance the light.py file wasn’t updated with my latest changes? It’s complaining about indentation - any chance you mixed spaces and tabs, maybe that’s the issue?

Multiple lights would be awesome, if I can help out with testing let me know!
Would help to know the BLE Mac address of the device it’s connected to, is it possible to add this as a sensor? (or see it in the logs)

Currently, the component is strictly one-way (the ESP32 controls the light, and doesn’t receive any information back), and the MAC address isn’t used for that control. The light simply listens to broadcast BLE traffic, and whatever packet matches the predefined structure (and, I think, includes an identifier that is broadcast during the 5-second pairing period) is processed and its command is executed. So as of now, knowing the MAC address of the light is irrelevant.

If you take a look at my code, specifically at the packet structure that’s being used in the send_packet method, one of the fields (called identifier) is set to a predefined value 0xcafebabe. I think that by using different values for different lights, control over separate lights is possible. But I’m not sure how to do it correctly on the ESPHome side.

I’d like to register a service per each instance of the light component (well, ideally - I’d like to register a single service, and receive the component instance as an argument to the service). But for some reason, I can’t seem to debug the LampSmartProLight::setup method properly - it’s definitely getting called (the service is registered), but I’m not sure at which point - and logging doesn’t work that early (maybe it would work over USB, I don’t know).

We’d need to generate a unique, 32-bit ID during construction of LampSmartProLight (and base it on the entity ID - another problem I faced, as I don’t seem to be able to get that info using ESPHome API). And then this ID would be used instead of 0xcafebabe, making each instance unique.

You’re welcome to give it a go and create a PR, if successful.

It is the Sonoff DualR3 and it is an ESP32 based with BLE. I am already using one as the Bluetooth Proxy.

I see. If you have any logs, I can try and help. Also, I think that using the BT proxy and the LampSmart Pro component on the same unit might not work - maybe that’s the issue?

Removed all of Bluetooth Proxy and still get error. Not sure where I went wrong? Log as below.

INFO Reading configuration /config/esphome/esp32-bluetooth-proxy-1856c8.yaml...
INFO Generating C++ source...
INFO Compiling app...
Processing esp32-bluetooth-proxy-1856c8 (board: esp32dev; framework: espidf; platform: platformio/[email protected])
--------------------------------------------------------------------------------
Removing unused dependencies...
Library Manager: Removing Improv @ 1.2.3
INFO Removing Improv @ 1.2.3
Library Manager: [email protected] has been removed!
INFO [email protected] has been removed!
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
 - framework-espidf @ 3.40404.0 (4.4.4) 
 - tool-cmake @ 3.16.4 
 - tool-ninja @ 1.7.1 
 - toolchain-esp32ulp @ 2.35.0-20220830 
 - toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5
Reading CMake configuration...
Generating assembly for certificate bundle...
Dependency Graph
|-- noise-c @ 0.1.4
|   |-- libsodium @ 1.10018.1
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/api/api_connection.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/api/api_frame_helper.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/api/api_pb2.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/api/api_pb2_service.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/api/api_server.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/api/list_entities.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/api/proto.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/api/subscribe_state.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/api/user_services.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/binary_sensor/automation.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/binary_sensor/binary_sensor.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/binary_sensor/filter.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/esp32/core.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/esp32/gpio.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/esp32/preferences.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/esp32_ble/ble.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/esp32_ble/ble_advertising.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/esp32_ble/ble_uuid.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/lampsmart_pro_light/lampsmart_pro_light.o
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/light/addressable_light.o
src/esphome/components/lampsmart_pro_light/lampsmart_pro_light.cpp: In function 'void esphome::lampsmartpro::ble_whiten(uint8_t*, uint8_t, uint8_t, uint8_t)':
src/esphome/components/lampsmart_pro_light/lampsmart_pro_light.cpp:73:44: error: suggest parentheses around '+' in operand of '&' [-Werror=parentheses]
     buf[i] ^= XBOXES[(seed + i + 9) & 0x1f + (salt & 0x3) * 0x20];
                                       ~~~~~^~~~~~~~~~~~~~~~~~~~~
src/esphome/components/lampsmart_pro_light/lampsmart_pro_light.cpp: In member function 'void esphome::lampsmartpro::LampSmartProLight::send_packet(uint16_t, uint8_t, uint8_t)':
src/esphome/components/lampsmart_pro_light/lampsmart_pro_light.cpp:163:4: warning: missing initializer for member 'esphome::lampsmartpro::adv_data_t::<unnamed struct>::crc16' [-Wmissing-field-initializers]
   }};
    ^
Compiling /data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/light/automation.o
cc1plus: some warnings being treated as errors
*** [/data/esp32-bluetooth-proxy-1856c8/.pioenvs/esp32-bluetooth-proxy-1856c8/src/esphome/components/lampsmart_pro_light/lampsmart_pro_light.o] Error 1
========================= [FAILED] Took 20.11 seconds =========================

My yaml config…

substitutions:

  devicename: esp32-bluetooth-proxy-1856c8

  friendly_name: Living BT-Proxy

esphome:

  name: $devicename

  name_add_mac_suffix: false

  friendly_name: $friendly_name

esp32:

  board: esp32dev

  framework:

    type: esp-idf

# Enable logging

logger:

  baud_rate: 0

  level: VERBOSE

# Enable Home Assistant API

api:

  encryption:

    key: !secret esphome_api_key

ota:

  password: !secret esphome_ota_password

wifi:

  ssid: !secret esphome_wifi_ssid

  password: !secret esphome_wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails

  ap:

    ssid: "$friendly_name Fallback Hotspot"

    password: !secret esphome_wifi_ap_password

#LampSmart Pro

external_components:

  # shorthand

  source: github://aronsky/esphome-components

sensor:

  - platform: uptime

    name: Uptime Sensor

  - platform: wifi_signal

    name: WiFi Signal

    update_interval: 60s

  - platform: template

    name: Free Memory

    lambda: return heap_caps_get_free_size(MALLOC_CAP_INTERNAL) / 1024;

    unit_of_measurement: 'kB'

    state_class: measurement

binary_sensor:

  - platform: status

    name: Status

#LampSmart Pro

light:

  - platform: lampsmart_pro_light

    name: Main Hallway

    duration: 1000

    default_transition_length: 0s

I’m not in front of my computer, so can’t verify versions. Can you try and remove the framework specification from your YAML? Might help… That definitely seems like some issue with a compiler version, since it’s complaining about syntax that’s treated correctly on my side…

Indeed that was the problem.:man_facepalming: Forgot to change that as Bluetooth Proxy needs the framework type as esp-idf.

It is now working but I do notice some issues (hopefully this component will only get better)…

  1. Does not dim down to as low as when control from app.
  2. Lights flicker when controlling the color temp as I guessed it is trying to get all 3 lights to be in sync.
  3. The temp color slider in HA also jumping around a little as the 3 lights get in sync.
  4. As you mentioned now it is only one way traffic thus HA not really showing the real settings of the lights. I have the lights connected to a main switch and it is still showing it as on even though main switch is already off.

Forgot to thank @aronsky for at least getting us ability to control the lights.

Indeed that was the problem.:man_facepalming: Forgot to change that as Bluetooth Proxy needs the framework type as esp-idf.

Great!

  1. Does not dim down to as low as when control from app.

Please see the latest changes (the progress was documented in this thread). Make sure that the latest version of the component is pulled from GitHub. Theoretically, you can go even lower than the now default minimum brightness of 7 using the configuration option - but I think that just updating to use the new minimum will fix it for you.

  1. Lights flicker when controlling the color temp as I guessed it is trying to get all 3 lights to be in sync.

Do you mean that you have 3 separate lights, and their color/brightness changes are slightly out of sync? It sort of makes sense. Basically, what this component does is broadcasting the newly requested brightness/color for the requested duration (set by the duration parameter). Due to the nature of BLE, the lights won’t necessarily pick up the message at exactly the same time (that’s also the reason the duration is that long, a whole second - to verify that the message is actually received and not lost).

  1. The temp color slider in HA also jumping around a little as the 3 lights get in sync.

Not sure whether it’s an actual issue with the code, or maybe the way Home Assistant works. The temp slider is not aware neither of the multiple lights, nor of their state. All it knows is the temperature actually set by ESPHome - and that should not fluctuate since you set the default transition to 0 (otherwise, it would fade from the previous temperature to the newly requested one, stepping through multiple values in the middle). I’d have to see it in action, but FWIW, that’s what other lights (unrelated to this component) work for me, as well. Do you have other lights with temperature/color control, that work differently?

  1. As you mentioned now it is only one way traffic thus HA not really showing the real settings of the lights. I have the lights connected to a main switch and it is still showing it as on even though main switch is already off.

Yep, I can imagine it’s frustrating, but no immediate solution to this. It’s worth emphasizing that 2-way communication might not even be possible - I know it didn’t working for me with the app (admittedly, I didn’t try for long). So just to set the expectations straight - don’t keep your hopes up for this specific feature :frowning:

Forgot to thank @aronsky for at least getting us ability to control the lights.

You’re welcome! :slightly_smiling_face:

I have a few questions besides the reply I gave below…

  1. How do I unpair the lights? I was thinking of pairing 1 of them to the app and the other 2 with your solutions to compare the lights in terms of brightness and color temp.
  2. How do I set the upper and lower limit of the color temp? Currently I see the max is 5988 and min is 3003. I wanted like 6500 and 2700.

Yes…it is exactly as how you have described the 3 lights and what you explained makes sense.

It only happens with the LampSmart Pro lights. I have other Tuya lights that are also group together and the control is very smooth and both lights change color and brightness in sync. I have attached 2 videos for comparison in your Github issues section as I am not able to attached video here.

I understand and even with the current control is already better than not able to control. :smiley: I did also notice the same behavior with the app as it is showing me as “ON” even though the main switch to the light is not on.

How do I unpair the lights? I was thinking of pairing 1 of them to the app and the other 2 with your solutions to compare the lights in terms of brightness and color temp.

There’s no proper “unpair” procedure. However, if you change the code to use a different identifier (currently, the hard-coded identifier is 0xcafebabe), I believe the lights will stop responding to it. Then you can use the pairing procedure with just one of the lights, and end up with only one light controlled by the ESP32 device.

How do I set the upper and lower limit of the color temp? Currently I see the max is 5988 and min is 3003. I wanted like 6500 and 2700

That’s achieved via the cold_white_color_temperature and warm_white_color_temperature configuration options, they are discussed earlier in this thread.

It only happens with the LampSmart Pro lights. I have other Tuya lights that are also group together and the control is very smooth and both lights change color and brightness in sync. I have attached 2 videos for comparison in your Github issues section as I am not able to attached video here.

This might be an issue between Home Assistant and ESPHome. There’s nothing in the code that should add such jumping. It’s also not happening on my end. Did you use the duration time of 0 and default transition length of 0 seconds, as per the sample configuration? If not, it might be possible that the transition is throwing it off.