Custom firmware ESPHome-Xiaomi_bslamp2

Yes, the repo is not compiling right now. I implemented the RGB table yesterday, and the code was left in a non-working state because of that. This causes the compilation errors that you saw.

I would love people to test my code base, but right now I would advise not to flash the device yet. If you want to test, it would also be wise to make a backup of the original firmware, so you can still go back to it (or use the backup that I included in my repo doc directory).
Note that the code does not yet cover all functionality. White light would work, RGB light is back in development now and the front panel is yet to be done.

If you try the version before yesterday’s commit, then the RGB light will somewhat work, but when using transitions you might encounter some strange flashy results.

1 Like

Hi mmakaay,
i want to use the bedlight as a alarm clock like before. At the moment this does not work anymore, beacause of the new firmware from xiaomi. But i need this on thuseday. I dont care if its not the exact sunrise on thuseday, but I would like that it goes on.

Now I have a problem witth flashing:


INFO Reading configuration /config/esphome/schlafzimmerbedlight.yaml...
INFO Generating C++ source...
INFO Compiling app...
INFO Running:  platformio run -d /config/esphome/schlafzimmerbedlight
Processing schlafzimmerbedlight (board: esp32doit-devkit-v1; framework: arduino; platform: [email protected])
--------------------------------------------------------------------------------
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
PACKAGES: 
 - framework-arduinoespressif32 0.0.0+sha.49b5f52 
 - tool-esptoolpy 1.20600.0 (2.6.0) 
 - toolchain-xtensa32 2.50200.80 (5.2.0)
Library Manager: Installing Hash
Library Manager: Already installed, built-in library
Dependency Graph
|-- <AsyncTCP-esphome> 1.1.1
|-- <ESPmDNS> 1.0
|   |-- <WiFi> 1.0
|-- <FS> 1.0
|-- <ESPAsyncWebServer-esphome> 1.2.7
|   |-- <AsyncTCP-esphome> 1.1.1
|   |-- <FS> 1.0
|   |-- <WiFi> 1.0
|-- <Wire> 1.0.1
|-- <DNSServer> 1.1.0
|   |-- <WiFi> 1.0
|-- <Update> 1.0
|-- <WiFi> 1.0
Retrieving maximum program size /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/firmware.elf
Checking size /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/firmware.elf
RAM:   [=         ]  12.5% (used 40904 bytes from 327680 bytes)
Flash: [=====     ]  49.3% (used 903786 bytes from 1835008 bytes)
========================= [SUCCESS] Took 9.16 seconds =========================
INFO Successfully compiled program.
INFO Running:  platformio run -d /config/esphome/schlafzimmerbedlight -t upload --upload-port /dev/ttyUSB0
Processing schlafzimmerbedlight (board: esp32doit-devkit-v1; framework: arduino; platform: [email protected])
--------------------------------------------------------------------------------
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
PACKAGES: 
 - framework-arduinoespressif32 0.0.0+sha.49b5f52 
 - tool-esptoolpy 1.20600.0 (2.6.0) 
 - tool-mkspiffs 2.230.0 (2.30) 
 - toolchain-xtensa32 2.50200.80 (5.2.0)
Library Manager: Installing Hash
Library Manager: Already installed, built-in library
Dependency Graph
|-- <AsyncTCP-esphome> 1.1.1
|-- <ESPmDNS> 1.0
|   |-- <WiFi> 1.0
|-- <FS> 1.0
|-- <ESPAsyncWebServer-esphome> 1.2.7
|   |-- <AsyncTCP-esphome> 1.1.1
|   |-- <FS> 1.0
|   |-- <WiFi> 1.0
|-- <Wire> 1.0.1
|-- <DNSServer> 1.1.0
|   |-- <WiFi> 1.0
|-- <Update> 1.0
|-- <WiFi> 1.0
Retrieving maximum program size /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/firmware.elf
Checking size /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/firmware.elf
RAM:   [=         ]  12.5% (used 40904 bytes from 327680 bytes)
Flash: [=====     ]  49.3% (used 903786 bytes from 1835008 bytes)
Configuring upload protocol...
AVAILABLE: esp-prog, espota, esptool, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa
CURRENT: upload_protocol = esptool
Looking for upload port...
Use manually specified: /dev/ttyUSB0
Uploading /data/schlafzimmerbedlight/.pioenvs/schlafzimmerbedlight/firmware.bin
Serial port /dev/ttyUSB0
Connecting....
Chip is unknown ESP32 (revision 1)
Features: WiFi, BT, Single Core, 240MHz, VRef calibration in efuse, Coding Scheme 3/4
MAC: 54:48:e6:5e:8a:f7
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 15872 bytes to 10319...

Writing at 0x00001000... (100 %)
Wrote 15872 bytes (10319 compressed) at 0x00001000 in 0.9 seconds (effective 136.8 kbit/s)...
File  md5: ad040c6561d840ef991cec238750dca1
Flash md5: 8a2c18be3cbf845188327c36bc860676
MD5 of 0xFF is 4206334261ccfe134c1e646c7de1ad8c

A fatal error occurred: MD5 of file does not match data in flash!
*** [upload] Error 2
========================= [FAILED] Took 11.43 seconds =========================

I also tried:

.local/bin/esptool.py -p /dev/ttyUSB0 erase_flash 
esptool.py v3.0
Serial port /dev/ttyUSB0
Connecting........_____....._____.....____
Detecting chip type... ESP32
Chip is unknown ESP32 (revision 1)
Features: WiFi, BT, Single Core, 240MHz, VRef calibration in efuse, Coding Scheme 3/4
Crystal is 40MHz
MAC: 54:48:e6:5e:8a:f7
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 0.0s
Hard resetting via RTS pin...
.local/bin/esptool.py -p /dev/ttyUSB0 write_flash  0x1000 ~/Downloads/schlafzimmerbedlight.bin 
esptool.py v3.0
Serial port /dev/ttyUSB0
Connecting.......
Detecting chip type... ESP32
Chip is unknown ESP32 (revision 1)
Features: WiFi, BT, Single Core, 240MHz, VRef calibration in efuse, Coding Scheme 3/4
Crystal is 40MHz
MAC: 54:48:e6:5e:8a:f7
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Compressed 903904 bytes to 507034...
Wrote 903904 bytes (507034 compressed) at 0x00001000 in 45.0 seconds (effective 160.7 kbit/s)...
File  md5: 3be5a32ce368e7264bfe6187480cd01b
Flash md5: 0c52b8c4699dff5828a599ddacce682f
MD5 of 0xFF is 1e7d690ccb15ea8cab3aa809688e1484

and

sven@merlin:~$ .local/bin/esptool.py -p /dev/ttyUSB0 erase_flash
esptool.py v3.0
Serial port /dev/ttyUSB0
Connecting.....
Detecting chip type... ESP32
Chip is unknown ESP32 (revision 1)
Features: WiFi, BT, Single Core, 240MHz, VRef calibration in efuse, Coding Scheme 3/4
Crystal is 40MHz
MAC: 54:48:e6:5e:8a:f7
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 0.0s
Hard resetting via RTS pin...
sven@merlin:~$ .local/bin/esptool.py -p /dev/ttyUSB0 write_flash  0x00000 ~/Downloads/schlafzimmerbedlight.bin 
esptool.py v3.0
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP32
Chip is unknown ESP32 (revision 1)
Features: WiFi, BT, Single Core, 240MHz, VRef calibration in efuse, Coding Scheme 3/4
Crystal is 40MHz
MAC: 54:48:e6:5e:8a:f7
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Compressed 903904 bytes to 507034...
Wrote 903904 bytes (507034 compressed) at 0x00000000 in 45.0 seconds (effective 160.6 kbit/s)...
File  md5: 3be5a32ce368e7264bfe6187480cd01b
Flash md5: e002f5ceb4e8fd33e20affc5407772c2
MD5 of 0xFF is 1e7d690ccb15ea8cab3aa809688e1484

Can anyone help, how to fix this?

I used the GUI for the ESPHome flasher to load the ESPHome firmware on it.
On my other lamp, I did use the command line tooling to backup and restore the original firmware (trying out my new firmware in-between), and there I ran into checksum issues. The command I used for this was on my windows box was:

python.exe .\esptool.py --chip esp32 --port COM3 --baud 115200 write_flash 0x00 .\yeelight_b2-orig-firmware.bin

IIRC, adding the --chip esp32 flag fixed it for me. A bit weird, since there’s some auto-detection that tells us that ESP32 is detected, but give that a go. I’m quite sure that was the issue for me when loading back the original firmware bin-file.

Failed with --chip esp32:

sven@merlin:~$ .local/bin/esptool.py --chip esp32  -p /dev/ttyUSB0 --baud 115200 write_flash  0x00 Downloads/schlafzimmerbedlight.bin 
esptool.py v3.0
Serial port /dev/ttyUSB0
Connecting......
Chip is unknown ESP32 (revision 1)
Features: WiFi, BT, Single Core, 240MHz, VRef calibration in efuse, Coding Scheme 3/4
Crystal is 40MHz
MAC: 54:48:e6:5e:8a:f7
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Compressed 903904 bytes to 507034...
Wrote 903904 bytes (507034 compressed) at 0x00000000 in 45.0 seconds (effective 160.6 kbit/s)...
File  md5: 3be5a32ce368e7264bfe6187480cd01b
Flash md5: 2fa6c2c4e45d5ac933c8356e09edaed7
MD5 of 0xFF is 1e7d690ccb15ea8cab3aa809688e1484

A fatal error occurred: MD5 of file does not match data in flash!

If you do another flash attempt after such failure, using the same bin file, do you then see the exact same “Flash md5” output? If you see different MD5 sums for the Flash md5, then the communication to the device might be flaky.

Maybe also interesting to know: how did you power the lamp board? What I have used, is an FTDI USB adapter, to which I only connected GND, TX and RX. I do not power the board from the FTDI power output (which supports 3.3V), but instead simply power the whole lamp using the regular power supply.

This gave me the best results with flashing the device and capturing its serial console output.

1 Like

Ow, here’s a fun thing… It seems that the struggle with the RGB colors is not really caused by my RGB implementation. I finished my new one (which I will keep anyway, much better than the first naive implementation), but I still found colors that were plain wrong when going through the RGB colors. Especially colors that involved blue.

I flashed the firmware to my Frankenstein-lamp, so I would be able to inspect if I was sending the correct GPIO load cycles, and this is what I found:

afbeelding

The blue channel reports 9764 Hz, where it should be 3kHz, like the red and green channel.
However, in my code, I do assign 3kHz as the frequency for that GPIO using ledc.
I do assign a requency of 9765 Hz to the white channel GPIO though. Here are the relevant setters in my code:

void set_blue_output(ledc::LEDCOutput *blue) {
    blue_ = blue;
    blue_->set_frequency(RGB_PWM_FREQUENCY);
}

void set_white_output(ledc::LEDCOutput *white) {
    white_ = white;
    white_->set_frequency(WHITE_PWM_FREQUENCY);
}

The generated code in main.cpp looks like:

rgbww_yeelightbs2lightoutput->set_white_output(led_white);
rgbww_yeelightbs2lightoutput->set_red_output(led_red);
rgbww_yeelightbs2lightoutput->set_green_output(led_green);
rgbww_yeelightbs2lightoutput->set_blue_output(led_blue);

Looking at the duty cycle levels, these assignments are correct. I do see the expected changes when changing colors. This means that the actual pin assignments in my device yaml file are correct.
It is just that the ledc frequency is somehow assigned to the wrong pin here.

It’s a bit late, so I might be overlooking an obvious issue here, but this feels a bit icky. At least I now know why my RGB colors are behaving badly, so I can now chase for a fix.

Update

I moved setting the frequencies out of my code into the device yaml. This gave the same results as before. So what I did next, was change up the order of the pin definitions like this:

  - platform: ledc
    id: led_blue
    pin: GPIO5
    frequency: 3kHz
  - platform: ledc
    id: led_red
    pin: GPIO13
    frequency: 3kHz
  - platform: ledc
    id: led_green
    pin: GPIO14
    frequency: 3kHz
  - platform: ledc
    id: led_white
    pin: GPIO12
    frequency: 10kHz

(I moved blue above the other pins).
Now I get other color issues, and they can be explained by the measurements:

afbeelding

It turns out that now my green GPIO is running at 10 kHz, while the blue one is now correct.
This makes it likely that this is a bug in the ledc code. I can’t find an obvious related bug report, so I will have to dig into this one myself.

*Note: I can set all the GPIO’s to 3kHz, including the white channel one. It is not what the original firmware does for that channel, but the results when using the white light mode do look okay to me. So if nothing else, that will be a possible quick fix.

Committed this quick fix + new RGB code in my latest commit to the repo.

3 Likes

Hurray,
I have successfull flashed the light with the regular power plugged in. I prepare a documentation of this and make you a pull request.

Sven

1 Like

Hi @Smurf ,
I want to make a flashing documentation pull reqeust. Is it okay to use your wire photos from Hacking Yeelight FW/enabling LAN control ?

No problem. Go ahead :+1:t2:

Started debugging the ledc frequency issues that I run into. I’ll document what I find in here.

First of all, I checked the console boot messages against the frequencies as used in my code. This shows:

[12:40:04][C][ledc.output:032]: LEDC Output:
[12:40:04][C][ledc.output:033]:   Pin GPIO13 (Mode: OUTPUT)
[12:40:04][C][ledc.output:034]:   LEDC Channel: 0
[12:40:04][C][ledc.output:035]:   Frequency: 3000.0 Hz
[12:40:04][C][ledc.output:032]: LEDC Output:
[12:40:04][C][ledc.output:033]:   Pin GPIO14 (Mode: OUTPUT)
[12:40:04][C][ledc.output:034]:   LEDC Channel: 1
[12:40:04][C][ledc.output:035]:   Frequency: 3000.0 Hz
[12:40:04][C][ledc.output:032]: LEDC Output:
[12:40:04][C][ledc.output:033]:   Pin GPIO5 (Mode: OUTPUT)
[12:40:04][C][ledc.output:034]:   LEDC Channel: 2
[12:40:04][C][ledc.output:035]:   Frequency: 3000.0 Hz
[12:40:04][C][ledc.output:032]: LEDC Output:
[12:40:04][C][ledc.output:033]:   Pin GPIO12 (Mode: OUTPUT)
[12:40:04][C][ledc.output:034]:   LEDC Channel: 3
[12:40:04][C][ledc.output:035]:   Frequency: 10000.0 Hz

These are the correct frequencies. This means that LEDCOutput::dump_config() is presenting the expected data here.
Also, each GPIO got its own unique PWM channel assigned, so the problem is not misassignment of those channels (as I expected, since I do measure distinct duty cycle levels on each output). So far so good.

I tried setting the frequency of the white light GPIO to 8888 Hz, to make sure that it’s this GPIO’s configuration that taints the blue output. This confirmed that it’s indeed the white light’s frequency that is used for blue. By turning on the white light mode, I could also confirm that the white light GPIO is also using that configured frequency.

I tried disabling the i2c components, just to be sure. As expected, this had no influence on the results.

Next stop was adding some extra debugging output to LEDCOutput::setup(), to check if the correct parameters were sent to the arduino-esp32 library. This looked good:

[13:03:36][W][ledc.output:029]: Attach channel 0 to pin 13 with frequency 3000.000000
[13:03:36][W][ledc.output:029]: Attach channel 1 to pin 14 with frequency 3000.000000
[13:03:36][W][ledc.output:029]: Attach channel 2 to pin 5 with frequency 3000.000000
[13:03:36][W][ledc.output:029]: Attach channel 3 to pin 12 with frequency 10000.000000

So, at this point, it looks like I have to drill deeper, down into the arduino-esp32 esp32-hal-ledc implementation. Unfortunately that is harder to debug, since I’m using pre-built library code here. Need coffee…

The coffee made me think: what if I define the white light frequency before the R, G, B frequencies? Well, that looked promising. The RGB GPIO’s used 3 kHz. However, this is what I saw when I turned on the white light:

afbeelding

Now an RGB channel clearly affected the frequency of the white light channel, which was now running at 3 kHz instead of the configured 10 kHz.

Curiously, I updated WRGB to respectively 10, 1, 2 and 3 kHz.
The result was a frequency of respectively 1, 1, 3 and 3, kHz.
So it looks like things go awry in pairs here. Let’s see when happens if I assign the pins in the order BGRW. This means the frequencies are respectively 3, 2, 1 and 10 kHz.
The result was a frequency of respectivley 2, 2, ? and 10 khz (the red channel couldn’t be read successfully and showed as constant HIGH, but I bet it was running at 10 kHz.

So based on this, it looks like every second ledc assignment sets the PWM frequency for both itself and its previous channel. This does shift attention to the PWM channel setup as described in the LEDC Chan to Group/Channel/Timer Mapping of the arduino-esp32 code. Looking at that, the four ledc PWM channels are mapped like this:

** ledc: 0  => Group: 0, Channel: 0, Timer: 0
** ledc: 1  => Group: 0, Channel: 1, Timer: 0
** ledc: 2  => Group: 0, Channel: 2, Timer: 1
** ledc: 3  => Group: 0, Channel: 3, Timer: 1

Interesting, right? Four channels, however the timers are overlapping. I find it very likely that it is simply a fact that the timers are shared for each pair of channels, and that you can therefore not set the frequencies independently. If this is the case, then the following configuration might be a working hack to get the outputs to behave:

  - platform: ledc
    id: led_ledc_timer_sharing_bugfix
    pin: GPIO12
  - platform: ledc
    id: led_white
    pin: GPIO12
  - platform: ledc
    id: led_red
    pin: GPIO13
  - platform: ledc
    id: led_green
    pin: GPIO14
  - platform: ledc
    id: led_blue
    pin: GPIO5

Well, look at that:

afbeelding

This fixes my issue, in quite a hacky way. The channels are now all running at their required frequencies. And of course, now I go back to the ledc component documentation, it clearly states:

channel ( Optional , int): Manually set the LEDC channel to use. Two adjacent channels share the same timer. Defaults to an automatic selection.

So after a bit of a round trip, I now understand the exact meaning of this snippet from the documentation and can therefore fix my setup by hard-coding some channels in the device yaml file. I went along and also moved the frequencies into this file. Check out the new example.yaml file for the updates that I did, and specifically the ledc output changes

(esp-ecially you @tabacha, since you were brave enough to flash your device already :wink: update the code and the YAML, which now includes channel + frequency, for the new goodness.)

3 Likes

To keep the codebase for the ESPHome custom component clean, I have split up the codebase and the reverse engineering documentation into two repositories:

1 Like

With the latest implementations for RGB, white light and night light, I have now come to the point to look at transitions. They do work, but I’m not satisfied with how they work.
I started a document in which I document my thought process on this one, because it is not something straight forward within the ESPHome light framework.

Update:

I did some more investigations on ways to improve the transitions. Unfortunately, I keep running into walls on this one. My latest findings are in the updated document.

Update:

Ah, now I’m getting somewhere I think. After my earlier investigation, I came to the conclusion that I wouldn’t be able to gain control over the transitioning behavior from within the LightOutput implementation. So I decided that the next best step might be to see if I could override the behavior of the LightState class and use that for my light. I had to dive a bit deeper into the code generation features of ESPHome, but I think I found the correct way to handle this.
See my updated document for details on this

So the next step is to create the actual override of the LightState class and see if I can gain enough control over the light’s transitioning behavior that way.

Update

So… next hurdle. I can have my own derived version of the LightState class. But looking at the LightState code, there’s virtually nothing (pun intended) in there that I can use for implementing the required behavior. There are only a few overridden methods from the Component class, but those don’t provide any useful hooks to do my thing.
I cannot simply hide the base class methods by re-implementing them, because the LightState is used in polymorphism constructs.Therefore, my re-implemented methods would not be visible to the calling code. So that’s a nono.

Next idea then: maybe I can add some accessors to my derived LightState class, to make it possible for my LightOutput impementation to get access to the now missing data.

Update

Yes, I got that to work. I now have a construct to access protected data from the LightState class from my LightOutput. I’m not completely happy with this though. I explained my concerns in the latest version of my document on this.

YEAH!!!

Getting the light transitions to behave in my ESPHome firmware was quite hard (because of what I see as a design flaw in the ESPHome light implementation, see my previous comments for details), but I’m happy to announce that I have managed to work around it, and now have very smooth transitions.

Not only within the RGB color space, but also in the white light space and the night light space and when transitioning between these color spaces! This is a huge improvement over the previous implementation and it is really close to the behavior of the original firmware.

The following demo video shows a couple of these transitions (note that brightness all the way down means “night light mode”, but it’s so faint that it barely shows on the video) and in the end, I enabled the fast random ESPHome light effect, which also looks really good now.

Three more thing to tackle (no biggies, these are simple from here on):

  • Smoothing out the transitions, like light::LightTransformer does for an even smoother flow.
  • When switching the light on, it’s on instantly without a transition.
  • When switching to a different color while a transition is in progress, the new transition will start at the original color from the previoius transition, instead of starting from the current state.
  • When restarting a transition to the same color as the one for an already active transition, the new transition will start at the original color, instead of continuing from the current state.

Tomorrow, I will handle these tasks, and I will do a final round of code cleanup on the color space implementations. Then it’s on to the front panel support.

I added a TL;DR section to my document in which I explored the options for implementing this.

Update:

I fixed the last few issues that were mentioned above, so it looks I can now dive into the front panel code :smiley: All updates are committed, for those who want the latest and greatest light implementation.

5 Likes

Looking really nice!!

1 Like

Excellent (o;

Just flashed my bedside lamp 2 which arrived today…

But looks the Kung Fu I2C touch stuff isn’t there yet?

cheers
richard

Yes, that is the next thing to tackle. I’m finishing up some last bits of light control code and then I’ll get whacking on the Kung Fu front panel stuff.

Perfect (o;

Though thought I look at the I2C tomorrow a little…but I am a little bit confused about your i2c github page (o;

Are those basically write 6 bytes to register 0x02 and read 6 bytes from register 0x04?

I don’t have these lamps bit I’ve been following this thread just because I’m in awe of the epic work going on here.

I’m tempted to get a few for the bedroom just because it looks like such a great job has been done, and hey no cloud :grin:

Can anyone clarify the exact model for these lamps? I’m not finding when searching for the BS2…

4 Likes

Can anyone clarify the exact model for these lamps?

You might want to search for " Xiaomi Mijia Bedside Lamp 2".
I bought mine as a “Yeelight Bedside Lamp 2”.

Are those basically write 6 bytes to register 0x02 and read 6 bytes from register 0x04?

All commands (write) and events (read) for the front panel (which has device ID 0x2C) consist of 6 bytes data. From what I saw on the bus, it didn’t look l ike registers were in play here. As I understood the signalling, the whole 6 byte code is the message to work with. Here’s one example of what I saw in my analyzer. The ESP32 addresses the device 0x2C and right away sends 6 bytes of data:

I did wonder if this was part of the I2C specs and this is what I found in a Texas Instruments document (PDF) back then:

While it is common to have registers in I2C slaves, please note that not all slave devices will have registers. Some devices are simple and contain only 1 register, which may be written directly to by sending the register data mmediately after the slave address, instead of addressing a register.

2 Likes

The original device firmware only supports night light “on” or “off”. In my firmware, I just implemented an option to combine the night light mode with an RGB setting, to make it possible to select a specific color for the night light mode.

In this demo video, I start with the light in normal mode, switch to night light mode by setting the brightness to its lowest value. After this I go through various RGB colors, before finally returning to normal RGB light mode with a higher brightness.

Note: In real live, the light is a lot more dimmed than it shows on the video. My phone camera clearly doesn’t know how to handle these different brightness levels of the device. It does show the variety in colors that you can get now though, which is the main part of this new feature.

2 Likes

Hi Maurice, hats off for the enormous effort you are spending here daily on an open-source project!

Do you think your firmware will be compatible with the bslamp v1? Apart from the front control, i assume that the backend will be pretty much identical?