@ -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 | |||