@ -1,126 +1,39 @@ | |||||
# esphome-xiaomi_bslamp2 | |||||
# ESPHome component for Xiaomi Mijia Bedside Lamp 2 | |||||
## Warning: this code is still under development | |||||
The Bedside Lamp 2 is a smart RGBWW LED lamp, produced by Yeelight. It can | |||||
be controlled via the WiFi network and using a touch panel on the front of | |||||
the device. The touch panel contains a power button, a button that changes | |||||
the color of the light and a slider that can be used to change the | |||||
brightness of the light. | |||||
This code might not yet be production-ready. | |||||
At this point, it is declared beta-quality. | |||||
This project provides a custom component for ESPHome, which makes it | |||||
possible to fully control every aspect of the lamp. | |||||
The new firmware is currently being tested and depending on the actual | |||||
use cases and issues that we might run into, breaking changes could still | |||||
occur at some point. | |||||
## Quick start guide | |||||
For those who have experience with flashing ESPHome onto devices, here's a | |||||
quick start guide: | |||||
## Is it safe to already install this firmware on my device? | |||||
* Clone the [GitHub repo](https://github.com/mmakaay/esphome-xiaomi_bslamp2) | |||||
into your ESPHome `config/custom_components` directory. | |||||
* Copy `config/custom_components/xiaomi_bslamp2/doc/example.yaml` to | |||||
`config/your_device_name.yaml` and modify it to your needs. | |||||
* Compile the `firmware.bin` file and download it to the device to which you | |||||
have connected a serial to USB adapter (FTDI). | |||||
* Open up the lamp and connect its `TX`, `RX`, `GND` and `GPIO0` debug pads | |||||
to the serial adapter (see the [detailed installation | |||||
guide](doc/install.md) for the debug pad locations). | |||||
* Power up the lamp with `GPIO0` connected to GND to enable flashing mode. | |||||
* Flash `firmware.bin` onto the device. | |||||
As long as you keep a backup of the original firmware, this is quite safe :-) | |||||
I have two lamps that both are running the latest development firmware and | |||||
they are functioning very well. | |||||
If you experience regular disconnects between Home Assistant and the lamp, | |||||
then take a look at the [known issues document](doc/known_issues.md). | |||||
I sometimes see API disconnection issues, but those can all be traced back | |||||
to the underlying frameworks. For the most prevalent issue, I did some | |||||
debugging and wrote a fix (it is mentioned below). | |||||
## Table of contents: | |||||
For each commit of the code, I will do my best to commit it in a working | |||||
state. Once a first completed stable release is cooked up, I will tag | |||||
production releases of the code to make it easier to pick the safe version | |||||
for production purposes. | |||||
* [Why custom firmware?](doc/why_custom_firmware.md) | |||||
* [Installation guide](doc/installation.md) | |||||
* [Configuration_guide](doc/configuration.md) | |||||
* [Flashing guide](doc/flashing.md) | |||||
* [Known issues](doc/known_issues.md) | |||||
## Installation | |||||
The code must be compiled using ESPHome. Therefore, a prerequisite is that | |||||
you have ESPHome up and running in some form (command line, docker container, | |||||
web dashboard, possibly from within Home Assistant). | |||||
For information on this, please refer to the documentation on the | |||||
[ESPHome website](https://esphome.io). | |||||
Create a folder named `custom_components` in the folder where your device's | |||||
yaml configuration file is stored. Then clone the the Github repo into a | |||||
subfolder `xiaomi_bslamp2`. For example on the command line: | |||||
``` | |||||
# mkdir custom_components | |||||
# cd custom_components | |||||
# git clone https://github.com/mmakaay/esphome-xiaomi_bslamp2 xiaomi_bslamp2 | |||||
``` | |||||
Your folder structure should now look like: | |||||
``` | |||||
config | |||||
├── yourdevice.yaml | |||||
├── custom_components/ | |||||
│ ├── xiaomi_bslamp2/ | |||||
│ . ├── README.md | |||||
. . ├── LICENSE.md | |||||
. . . | |||||
``` | |||||
On a Rapsbery Pi with HomeAssistant and ESPHome as a plugin, the directory | |||||
should be: `/config/esphome/custom_components/xiaomi_bslamp2/` | |||||
``` | |||||
config | |||||
├── esphome | |||||
│ ├── yourdevice.yaml | |||||
│ ├── custom_components/ | |||||
| . ├── xiaomi_bslamp2/ | |||||
│ . . ├── README.md | |||||
. . . ├── LICENSE.md | |||||
. . . . | |||||
``` | |||||
Then create the required configuration in your device's yaml configuration | |||||
file. For an example file, take a look at the example file | |||||
[doc/example.yaml](doc/example.yaml) in this repository. | |||||
After these steps you can compile your firmware `firmware.bin` file. | |||||
This firmware can then be flashed onto the device. | |||||
Like normal with ESPHome, the first time you will have to flash the | |||||
device using a serial interface. After this initial flashing operation, you | |||||
can flash new versions of the firmware using the OTA (Over The Air) method. | |||||
See [doc/FLASHING.md](doc/FLASHING.md) for hints on opening up the device and | |||||
flashing its firmware using the serial interface. | |||||
## Issue: the device keeps losing its connection to Home Assistant | |||||
This is not a problem with the device or the custom firmware, but a problem | |||||
in the upstream library "AsyncTCP". I did identify an issue and my pull | |||||
request for a fix was accepted and merged: | |||||
https://github.com/OttoWinter/AsyncTCP/pull/4 | |||||
This fix will likely be available in the next release of ESPHome | |||||
(the current version at the time of writing is 1.16.2). | |||||
If you want to try out this fix on beforehand, then create a `libs` folder | |||||
in the folder where your device's yaml configuration file is stored (e.g. | |||||
when using the Home Assistant plugin: `/config/esphome/libs/`). | |||||
Then clone the following repository into that folder: | |||||
https://github.com/OttoWinter/AsyncTCP | |||||
For example on the command line: | |||||
``` | |||||
# cd /config/esphome | |||||
# mkdir libs | |||||
# cd libs | |||||
# git clone https://github.com/OttoWinter/AsyncTCP | |||||
``` | |||||
Then add a pointer to this folder from within your device's yaml | |||||
configuration file, using the `lib_extra_dirs` option. Provide it with the | |||||
absolute path to your `libs` folder. The relevant part of the config change | |||||
looks like this (matching the example from above): | |||||
```yaml | |||||
esphome: | |||||
platformio_options: | |||||
lib_extra_dirs: /config/esphome/libs | |||||
``` | |||||
This way, the repository version of the library will override the version of | |||||
the library that is bundled with ESPHome. Build the device firmware and | |||||
flash the device like you would normally do. |
@ -1,189 +0,0 @@ | |||||
# Flashing the Xiaomi Mijia Bedside Lamp 2 | |||||
## Tools needed | |||||
* Allen key (2mm, 5/64") or torx (T8) screw driver | |||||
* Soldering Iron | |||||
* Perhaps some sticky tape | |||||
* A serial to USB adapter (FTDI) | |||||
* Some wires | |||||
## Warning | |||||
We have writen these instructions with care, but we will give absolutely no | |||||
warranty. Perhaps you will destroy your device and your computer. | |||||
## Opening the lamp, to expose the PCB | |||||
Remove the rubber pads from the botton of the lamp. | |||||
Unbolt the 4 screws which were hidden by the rubber pads. | |||||
![Photo of the screws](images/screws.jpg "Use an allen key or torx screw driver to remove the screws.") | |||||
Remove the bottom from the device, exposing the PCB. | |||||
This might take a bit of force. Just pull it up bit by bit until it pops loose. | |||||
For some good pictures of disassembling this device, take a look | |||||
[at this blog post](https://mysku.ru/blog/china-stores/78455.html) | |||||
It is in Russian, but the translation by Google works well and moreover, the | |||||
pictures are the most important thing here. If you scroll down, you will | |||||
find them easily. | |||||
## Solder the wires | |||||
Many of the serial to USB adapter have some header pins to which you can | |||||
connect the wires of a device. Therefore, I find it most useful to take some | |||||
dupont wires with a female end to them, and cut off the other end. Strip the | |||||
wire on the other and, and then it can be used to solder it to the board. | |||||
Solder the wires to the RX, TX, GND and GPIO0 debug pads that are shown in this | |||||
photo. It is not required to solder a wire to the 3.3V debug pad. This pad | |||||
is not directly connected to the 3.3V Vin of the ESP32 chip, making it a | |||||
less than optimal candidate for powering the board during flashing. Instead, | |||||
powering the lamp using its own power supply works best. | |||||
![Soldering points](images/Soldering_points.jpg) | |||||
You can use some sticky tape to fixate the cables before soldering. | |||||
## Connect the wires to your serial to USB device | |||||
The wires must be connected as follows: | |||||
| Soldering point| Serial USB Adapter name | | |||||
| -------------- |:------------------------:| | |||||
| GND | GND | | |||||
| TX | RX | | |||||
| RX | TX | | |||||
| GPIO0 | GND | | |||||
To be able to flash the device, GPIO0 must be connected to ground while the | |||||
device is booted. Therefore, connect these wires before plugging in the | |||||
device's power adapter. Flashing will not work if you connect these wires | |||||
when the device has already been powered up. | |||||
## When you only have one GND pin on your USB Adapter | |||||
If your USB Adapter does not have multiple GND pins, then you'll have | |||||
to find another way to attach GPIO0 to ground. Some options: | |||||
- Use a breadbord, so you can connect the USB Adapter GND pin to a row on | |||||
the bread bord, and connect the GND and GPIO0 wires of the board to that | |||||
same row. | |||||
- Solder a button on the board that connects GPIO0 to GND when pressed. Then | |||||
you can hold down this button while plugging in the device's power supply. | |||||
After booting up, you can release the button (the serial console will also | |||||
mention that the device is now in flash mode). This is not the most | |||||
practical solution for most people (since only one such flash operation is | |||||
needed, from then on OTA - Over The Air - updates are possible), but it | |||||
was a great help to me during the initial reverse engineering and firmware | |||||
development. | |||||
- Manually hold a wire connected to both a GND surface (e.g. the silver pad | |||||
on the left of the board) and the GPIO0 debug pad, while plugging in the | |||||
power supply. After booting, the wire can be removed. This is very fiddly | |||||
way of doing it, but I did it a few times and it can be done. | |||||
- You could opt for temporarily soldering a lead between GND and GPIO0 on | |||||
the board, making GPIO0 pulled to ground permanently. It is a bit less | |||||
flexible than some other options, but if you only need to do the initial | |||||
backup and firmware flash of the device, then this can bee all that you | |||||
need. Remove the lead after flashing is done, otherwise the device won't | |||||
boot in normal mode. | |||||
## Download and install esptool | |||||
See: https://github.com/espressif/esptool/blob/master/README.md#installation--dependencies | |||||
## Make a backup of the current firmware | |||||
Here's an example on how to backup the original firmware from Linux. First, | |||||
unplug your device's power supply, then start the esptool read_flash command: | |||||
``` | |||||
python esptool.py -p /dev/ttyUSB0 read_flash 0x0 0x400000 original-firmware.bin | |||||
``` | |||||
/dev/ttyUSB0 is the port of the usb adaper on Linux. You can find what port | |||||
is used by the adapter by running `dmesg` after plugging in the USB device. | |||||
On Windows this is often `COM1`, `COM2` or `COM3`. | |||||
Now plug in the power supply. The output of esptool should now show that it | |||||
connects to the device and downloads the firmware from it. | |||||
**Caution**: You will find the WLAN SSID and Password of the latest used WiFi in | |||||
this file. Therefore, keep this backup in a safe place. | |||||
## Restore the backed up firmware | |||||
In case you need to rollback to the device's original firmware at some point, | |||||
here's an example of how to restore the original firmware from Windows, by fully | |||||
flashing it back onto the device. | |||||
First, unplug your device's power supply, then start the esptool write_flash command: | |||||
``` | |||||
python.exe .\esptool.py --chip esp32 --port COM3 --baud 115200 write_flash 0x00 original-firmware.bin | |||||
``` | |||||
Make sure that GPIO0 is connected to GND and plug in the power supply. | |||||
The output of esptool should now show that it connects to the device and uploads | |||||
the firmware to it. Be patient after the upload reaches 100%. The output is | |||||
silent for a while, but esptool tool is verifying if the firmware was uploaded | |||||
correctly. | |||||
After the firmware was uploaded, unplug the power, disconnect GPIO0 from GND and | |||||
reconnect the power to boot into the restored firmware. | |||||
## Flash new firmware | |||||
Setup an ESPHome Project (see [README.md](../README.md)),compile the firmware | |||||
for the device and download the `firmware.bin` file to the device to which | |||||
the serial adapter is connected. | |||||
You can flash the device using esphome or esptool. | |||||
I normally use the [esphome-flasher](https://github.com/esphome/esphome-flasher) | |||||
tool, which is a very easy to use GUI utility app for flashing ESPHome devices: | |||||
- In the app, select the COM port of your serial adapter | |||||
- Also select the firmware.bin file to flash onto the device | |||||
- Power up the device with GPIO0 connected to GND | |||||
- Click the "Flash ESP" button to flash the firmware. | |||||
If you want to flash with esptool, you can use: | |||||
``` | |||||
python.exe .\esptool.py --chip esp32 --port COM3 --baud 115200 write_flash 0x1000 <path\to\yourfirmware.bin> | |||||
``` | |||||
After flashing, power down the device, disconnect GPIO0 from GND and reconnect | |||||
the power to boot into the ESPHome firmware. | |||||
From here on, it is possible to flash the device OTA (over the air, which | |||||
means that the firmware is uploaded over WiFi) from ESPHome. Therefore, it | |||||
is now time to tuck away or remove those soldered wires and add the bottom | |||||
cover back on. | |||||
## Troubleshooting flash | |||||
If you have **A fatal error occurred: MD5 of file does not match data in | |||||
flash!**, then make sure you are powering the board using the device's own | |||||
power adapter. We've seen these errors when trying to power the board using | |||||
the 3.3V debug pad. | |||||
After seeing this error, user @tabacha was able to successfully flash his | |||||
device using the regular power adapter and the tasmota boot loader using | |||||
the following command: | |||||
``` | |||||
python esptool.py --chip esp32 -p /dev/ttyUSB0 --baud 115200 --before default_reset --after hard_reset write_flash -z --flash_mode dout --flash_freq 40m --flash_size detect 0x1000 bootloader_dout_40m.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 ~/Downloads/schlafzimmerbedlight.bin | |||||
``` | |||||
You will find the missing tasmota boot files here: | |||||
https://github.com/arendst/Tasmota/tree/firmware/firmware/tasmota32/ESP32_needed_files | |||||
*Note: user @tabacha was not able to use tasmota with the Bedside Lamp 2.* | |||||
(remember that the [esphome-flasher](https://github.com/esphome/esphome-flasher) | |||||
will give you a bit less of a hard-core experience during flashing) |
@ -0,0 +1,3 @@ | |||||
# Configuration guide | |||||
TODO |
@ -0,0 +1,197 @@ | |||||
# Flashing guide | |||||
## Tools needed | |||||
* Allen key (2mm, 5/64") or torx (T8) screw driver | |||||
* Soldering Iron | |||||
* Perhaps some sticky tape | |||||
* A serial to USB adapter (FTDI) | |||||
* Some wires | |||||
## Warning | |||||
We have writen these instructions with care, but we will give absolutely no | |||||
warranty. Perhaps you will destroy your lamp and your computer. | |||||
## Opening the lamp, to expose the PCB | |||||
Remove the rubber pads from the botton of the lamp, to get access to 4 | |||||
screws that attach the bottom to the rest of the lamp. Note that you don't | |||||
have to remove these pads fully. Once you can access the screws, you've | |||||
gone far enough. | |||||
Unbolt the 4 screws which were hidden under the rubber pads. | |||||
![Photo of the screws](images/screws.jpg "Use an allen key or torx screw driver to remove the screws.") | |||||
Detach the bottom from the rest of the lamp, exposing the PCB. This might | |||||
take a bit of force. Just pull it up bit by bit until it pops loose. | |||||
For some good pictures of disassembling this lamp, take a look [at this | |||||
blog post](https://mysku.ru/blog/china-stores/78455.html) It is in Russian, | |||||
but the translation by Google works well and moreover, the pictures are the | |||||
most important thing here. If you scroll down, you will find them easily. | |||||
## Solder the wires | |||||
Many of the serial to USB adapter have some header pins to which you can | |||||
connect the wires of a device. Therefore, I find it most useful to take some | |||||
dupont wires with a female end to them, and cut off the other end. Strip the | |||||
wire on the other and, and solder this end to the board. | |||||
Solder the wires to the `RX`, `TX`, `GND` and `GPIO0` debug pads that are | |||||
shown in the following photo. It is *not* required to solder a wire to the | |||||
`3.3V` debug pad. This pad is not directly connected to the 3.3V Vin of the | |||||
ESP32 chip, making it a less than optimal candidate for powering the board | |||||
during flashing. Instead, powering the lamp using its own power supply works | |||||
best. | |||||
![Soldering points](images/Soldering_points.jpg) | |||||
You can use some sticky tape to fixate the cables before soldering. | |||||
## Connect the wires to your serial to USB adapter | |||||
The wires must be connected as follows: | |||||
| Soldering point| Serial USB Adapter name | | |||||
| -------------- |:------------------------:| | |||||
| GND | GND | | |||||
| TX | RX | | |||||
| RX | TX | | |||||
| GPIO0 | GND | | |||||
To be able to flash the lamp, `GPIO0` must be connected to ground while | |||||
the lamp boots up. Therefore, connect these wires *before* plugging in | |||||
the lamp's power supply. Flashing will not work if you connect these | |||||
wires after the lamp has already been booted up. | |||||
## When you only have one GND pin on your USB Adapter | |||||
If your USB Adapter does not have multiple `GND` pins, then you'll have to | |||||
find another way to attach `GPIO0` to ground. Some options: | |||||
- Use a breadbord, so you can connect the USB Adapter `GND` pin to a row on | |||||
the bread bord, and connect the `GND` and `GPIO0` wires of the lamp's | |||||
board to that same row. | |||||
- Solder a button on the board that connects `GPIO0` to `GND` when pressed. | |||||
Then you can hold down this button while plugging in the lamp's power | |||||
supply. After booting up, you can release the button (the serial console | |||||
will also mention that flash mode is now enabled). This is not the most | |||||
practical solution for most people (since only one such flash operation is | |||||
needed, from then on OTA - Over The Air - updates are possible), but it | |||||
was a great help to me during the initial reverse engineering and firmware | |||||
development. | |||||
- Manually hold a wire connected to both a GND surface (e.g. the silver pad | |||||
on the left of the board) and the `GPIO0` debug pad, while plugging in the | |||||
power supply. After booting, the wire can be removed. This is very fiddly | |||||
way of doing it (a third hand would be very welcome with this), but it can | |||||
be done. | |||||
- You could opt for temporarily soldering a lead between `GND` and `GPIO0` | |||||
on the board, making `GPIO0` pulled to ground permanently. It is a bit | |||||
less flexible than some other options, but if you only need to do the | |||||
initial backup and firmware flash of the lamp, then this can be all | |||||
that you need. Remove the lead after flashing is done, otherwise the | |||||
lamp won't boot in normal mode. | |||||
## Make a backup of the current firmware | |||||
Backing up the firmware makes it possible to revert to the original firmware, | |||||
in case you have problems with the ESPHome firmware. The backup can be | |||||
created using "esptool". Installation instructures can be found here: | |||||
https://github.com/espressif/esptool/blob/master/README.md#installation--dependencies | |||||
Here's an example on how to backup the original firmware from Linux. First, | |||||
unplug your lamp's power supply, then start the esptool read_flash command: | |||||
``` | |||||
python esptool.py -p /dev/ttyUSB0 read_flash 0x0 0x400000 original-firmware.bin | |||||
``` | |||||
`/dev/ttyUSB0` is the port of the USB adaper on Linux. You can find what | |||||
port is used by the adapter by running `dmesg` after plugging in the USB | |||||
device. On Windows this is often `COM1`, `COM2` or `COM3`. | |||||
Now plug in the power supply. The output of esptool should now show that it | |||||
connects to the lamp and downloads the firmware from it. | |||||
**Caution**: You will find the WLAN SSID and Password of the last used | |||||
WiFi network in this file. Therefore, keep this backup in a safe place. | |||||
## Restore the backed up firmware | |||||
In case you need to rollback to the lamp's original firmware at some | |||||
point, here's an example of how to restore the original firmware from | |||||
Windows, by fully flashing it back onto the lamp. | |||||
First, unplug your lamp's power supply, then start the esptool write_flash | |||||
command: | |||||
``` | |||||
python.exe .\esptool.py --chip esp32 --port COM3 --baud 115200 write_flash 0x00 original-firmware.bin | |||||
``` | |||||
Make sure that `GPIO0` is connected to GND and plug in the power supply. | |||||
The output of esptool should now show that it connects to the lamp and | |||||
uploads the firmware to it. Be patient after the upload reaches 100%. The | |||||
output is silent for a while, but esptool tool is verifying if the firmware | |||||
was uploaded correctly. | |||||
After the firmware upload completes, unplug the power, disconnect `GPIO0` | |||||
from GND and reconnect the power supply to boot into the restored firmware. | |||||
## Flash new ESPHome firmware | |||||
Setup an ESPHome Project (see [README.md](../README.md)),compile the firmware | |||||
for the lamp and download the `firmware.bin` file to the device to which | |||||
the serial adapter is connected. | |||||
You can flash the lamp using esphome or esptool. I would recommend using | |||||
the [esphome-flasher](https://github.com/esphome/esphome-flasher) tool, | |||||
which is a very easy to use GUI utility app for flashing ESPHome devices: | |||||
- In the app, select the COM port of your serial adapter. | |||||
- Also select the firmware.bin file to flash onto the lamp. | |||||
- Power up the lamp with `GPIO0` connected to GND. | |||||
- Click the "Flash ESP" button to flash the firmware. | |||||
If you want to flash with esptool, you can use: | |||||
``` | |||||
python.exe .\esptool.py --chip esp32 --port COM3 --baud 115200 write_flash 0x1000 <path\to\yourfirmware.bin> | |||||
``` | |||||
After flashing, power down the lamp, disconnect `GPIO0` from GND and | |||||
reconnect the power to boot into the new ESPHome firmware. | |||||
From here on, it is possible to flash the lamp OTA (over the air, which | |||||
means that the firmware is uploaded over WiFi) from ESPHome. Therefore, it | |||||
is now time to tuck away or remove those soldered wires and add the bottom | |||||
cover back on. | |||||
## Troubleshooting flash | |||||
If you have **A fatal error occurred: MD5 of file does not match data in | |||||
flash!**, then make sure you are powering the board using the lamp's own | |||||
power adapter. We've seen these errors when trying to power the board using | |||||
the 3.3V debug pad. | |||||
After seeing this error, user @tabacha was able to successfully flash his | |||||
lamp using the regular power adapter and the tasmota boot loader using | |||||
the following command: | |||||
``` | |||||
python esptool.py --chip esp32 -p /dev/ttyUSB0 --baud 115200 --before default_reset --after hard_reset write_flash -z --flash_mode dout --flash_freq 40m --flash_size detect 0x1000 bootloader_dout_40m.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 ~/Downloads/schlafzimmerbedlight.bin | |||||
``` | |||||
You will find the missing tasmota boot files here: | |||||
https://github.com/arendst/Tasmota/tree/firmware/firmware/tasmota32/ESP32_needed_files | |||||
*Note: user @tabacha was not able to use tasmota with the Bedside Lamp 2.* | |||||
(remember that the [esphome-flasher](https://github.com/esphome/esphome-flasher) | |||||
will give you a bit less of a hard-core experience during flashing) |
@ -0,0 +1,59 @@ | |||||
# Installation guide | |||||
The code must be compiled using ESPHome. Therefore, a prerequisite is that | |||||
you have ESPHome up and running in some form (command line, docker container, | |||||
web dashboard, possibly from within Home Assistant). | |||||
For information on this, please refer to the documentation on the | |||||
[ESPHome website](https://esphome.io). | |||||
Create a folder named `custom_components` in the folder where your device's | |||||
yaml configuration file is stored. Then clone the the Github repo into a | |||||
subfolder `xiaomi_bslamp2`. For example on the command line: | |||||
``` | |||||
# cd /your/path/to/config | |||||
# mkdir custom_components | |||||
# cd custom_components | |||||
# git clone https://github.com/mmakaay/esphome-xiaomi_bslamp2 xiaomi_bslamp2 | |||||
``` | |||||
Your folder structure should now look like: | |||||
``` | |||||
config | |||||
├── yourdevice.yaml | |||||
├── custom_components/ | |||||
│ ├── xiaomi_bslamp2/ | |||||
│ . ├── README.md | |||||
. . ├── LICENSE.md | |||||
. . . | |||||
``` | |||||
On a Rapsbery Pi with HomeAssistant and ESPHome as a plugin, the directory | |||||
should be: `/config/esphome/custom_components/xiaomi_bslamp2/` | |||||
``` | |||||
config | |||||
├── esphome | |||||
│ ├── yourdevice.yaml | |||||
│ ├── custom_components/ | |||||
| . ├── xiaomi_bslamp2/ | |||||
│ . . ├── README.md | |||||
. . . ├── LICENSE.md | |||||
. . . . | |||||
``` | |||||
Then create the required configuration in your device's yaml configuration | |||||
file. For an example file, take a look at the example file | |||||
[doc/example.yaml](doc/example.yaml) in this repository. | |||||
Detailed configuration instructions can be found in the | |||||
[Configuration guide](doc/configuration.md). | |||||
After these steps you can compile your firmware `firmware.bin` file. | |||||
This firmware can then be flashed onto the device. | |||||
Like normal with ESPHome, the first time you will have to flash the | |||||
device using a serial interface. After this initial flashing operation, you | |||||
can flash new versions of the firmware using the OTA (Over The Air) method. | |||||
See [doc/flashing.md](the flashing guide) for hints on opening up the | |||||
device and flashing its firmware using its serial interface. |
@ -0,0 +1,83 @@ | |||||
# Known issues | |||||
## The device keeps losing its connection to Home Assistant | |||||
Disconnects are annoying, but even more annoying is that sometimes the | |||||
lamp will reboot (during which the light will be turned off) as a result of | |||||
these disconnects. The reasons for these reboots are very likely in the | |||||
underlying libraries, and I'm working on tracking these down. | |||||
In the meanwhile, there are a few factors that you can look at to bring down | |||||
the number of disconnects: | |||||
* A bug in the AsyncTCP library | |||||
* The number of connected API clients | |||||
* The logging output level | |||||
**A bug in the AsyncTCP library** | |||||
You might be running into a problem in the upstream library "AsyncTCP". | |||||
If you connect a serial console to your lamp and see "ack timeout 4" | |||||
messages in the logging output before the lamp disconnects the API client, | |||||
then you can be pretty sure that this is the culprit. | |||||
I did identify the underlying issue and a pull request for a fix was | |||||
accepted and merged into the ESPHome fork of the library: | |||||
https://github.com/OttoWinter/AsyncTCP/pull/4 | |||||
This fix will likely be available in the next release of ESPHome | |||||
(the current version at the time of writing is 1.16.2). | |||||
If you want to try out this fix on beforehand, then create a `libs` folder | |||||
in the folder where your device's yaml configuration file is stored (e.g. | |||||
when using the Home Assistant plugin: `/config/esphome/libs/`). | |||||
Then clone the following repository into that folder: | |||||
https://github.com/OttoWinter/AsyncTCP | |||||
For example on the command line: | |||||
``` | |||||
# cd /config/esphome | |||||
# mkdir libs | |||||
# cd libs | |||||
# git clone https://github.com/OttoWinter/AsyncTCP | |||||
``` | |||||
Then add a pointer to this folder from within your device's yaml | |||||
configuration file, using the `lib_extra_dirs` option. Provide it with the | |||||
absolute path to your `libs` folder. The relevant part of the config change | |||||
looks like this (matching the example from above): | |||||
```yaml | |||||
esphome: | |||||
platformio_options: | |||||
lib_extra_dirs: /config/esphome/libs | |||||
``` | |||||
This way, the repository version of the library will override the version of | |||||
the library that is bundled with ESPHome. Build the device firmware and | |||||
flash the device like you would normally do. | |||||
**The number of connected API clients** | |||||
Another factor on the connection stability, seems to be the number of | |||||
clients that are connected to the API. When connecting a log client via the | |||||
API (e.g. when looking at the logging from within the web dashboard), while | |||||
Home Assistant is also connected, disconnects might occur. | |||||
When the lamp is in production, this is not an issue. Then only Home | |||||
Assistant is connected. | |||||
**The logging output level** | |||||
I have seen an increase in disconnects while the log level was set to | |||||
`VERY_VERBOSE`. The logging code might take up so much time, that it | |||||
interferes with the operation of the networking code. Especially since the | |||||
ESP32-WROOM-32D chip that is used in the lamp is a single core version of | |||||
the ESP32. | |||||
For this reason, I advise to completely omit logging or use a very low log | |||||
level for production purposes. | |||||
@ -0,0 +1,37 @@ | |||||
# Why custom ESPHome firmware? | |||||
This lamp could always be added to Home Assistant using the Yeelight | |||||
integration. For this to work, the lamp had to be configured to enable a | |||||
special "LAN control" option, which provides the interface that the Yeelight | |||||
integration could talk to. | |||||
January 2021, Xiaomi decided to remove the LAN control option from the | |||||
firmware. Information about this can be found on the Yeelight forums: | |||||
https://forum.yeelight.com/t/topic/22664 | |||||
In the forums, a work-around is offered: by providing your Mi ID, you can be | |||||
added to some mythical white list, through which you'll get a special | |||||
firmware upgrade that does have LAN control enabled. After that, no further | |||||
ugprades should be done. | |||||
This just didn't feel right, so I started looking into alternative solutions | |||||
to regain control over the lamp. After opening it up, I was pleased to | |||||
find an ESP32-WROOM-32D chip inside, meaning that it might be possible to | |||||
build my own firmware for it using ESPHome. | |||||
On the Home Assistant community forums, I found an existing thread where | |||||
people already started poking at the lamp. | |||||
https://community.home-assistant.io/t/hacking-yeelight-fw-enabling-lan-control/284406 | |||||
I joined the discussion and started poking as well. Some things turned out | |||||
to be more complicated than anticipated and quite a bit of reverse | |||||
engineering was required to make things work, but eventually this all | |||||
resulted in working firmware. | |||||
Documents related to the reverse engineering process can be found in a | |||||
separate GitHub repository: | |||||
https://github.com/mmakaay/esphome-yeelight_bs2-revengineering | |||||