Browse Source

Add start of Chinese doc translation

release/2022.12.0
Maurice Makaay 2 years ago
parent
commit
10687aed37
9 changed files with 1454 additions and 0 deletions
  1. +460
    -0
      doc_chinese/configuration.md
  2. +287
    -0
      doc_chinese/flashing.md
  3. +38
    -0
      doc_chinese/installation.md
  4. +37
    -0
      doc_chinese/release_plan.md
  5. +20
    -0
      doc_chinese/sponsoring.md
  6. +381
    -0
      doc_chinese/technical_details.md
  7. +73
    -0
      doc_chinese/test_plan.md
  8. +123
    -0
      doc_chinese/upgrading_to_2021.10.0.md
  9. +35
    -0
      doc_chinese/why_custom_firmware.md

+ 460
- 0
doc_chinese/configuration.md View File

@ -0,0 +1,460 @@
< [Installation guide](installation.md) | [Index](../README.md) | [Flashing guide](flashing.md) >
# Configuration guide
I think, the best starting point for creating your own yaml configuration, is to look at the
[`example.yaml`](../example.yaml) file and the [configuration packages](../packages).
These configuration files were written with the functionality of the original firmware in
mind and it makes use of all available options. This configuration guide can be used to fill
in the blanks.
The `xiaomi_bslamp2` platform provides various components that expose the core functionalities of
the lamp. In the following table, you can find what components are used for exposing what physical
components of the lamp.
| Part | Component(s) |
| -------------------------- |------------------------------------------------------------------|
| ESP32 pinouts | [platform xiaomi_bslamp2](#platform-xiaomi_bslamp2) |
| RGBWW LEDs | [light](#light) |
| Front Panel Power button | [binary_sensor](#component-binary_sensor) |
| Front Panel Color button | [binary_sensor](#component-binary_sensor) |
| Front Panel Slider | [binary_sensor](#component-binary_sensor) (touch/release) |
| | [sensor](#component-sensor) (touched slider level) |
| Front Panel Illumination | [output](#component-output) (on/off + indicator level) |
| Light mode propagation | [text_sensor](#component-text_sensor) |
## Platform: xiaomi_bslamp2
At the core of the hardware support is the `xiaomi_bslamp2` platform, which provides two hub-style
hardware abstraction layer (HAL) components that are used by the other components: one for driving
the GPIO's for the RGBWW leds and one for the I2C communication between the ESP32 and the front
panel.
You will not have to add any configuration options for the `xiaomi_bslamp2` to your yaml file.
The required configuration is fully provided by the configuration package `packages/core.yaml`.
The GPIO + I2C configurations are prepared to work for the Bedside Lamp 2 wiring out of the box.
```yaml
xiaomi_bslamp2:
```
The only reason that I can think of for adding this platform configuration to your yaml file, would
be if you blew one or more or the ESP32 pins, and need to rewire functionality. In other cases,
simply omit the section.
## Component: light
The light component creates an RGBWW light. This means that it can do colored light and cold/warm
white light based on a color temperature.
```yaml
light:
- platform: xiaomi_bslamp2
name: My Bedside Lamp
id: my_bedside_lamp
default_transition_length: 0.5s
effects:
- random:
name: Randomize
transition_length: 3s
update_interval: 3s
on_brightness:
- then:
- logger.log: The brightness changed!
presets:
my_color_presets:
red: { red: 100%, green: 0%, blue: 0% }
green: { red: 0%, green: 100%, blue: 0% }
blue: { red: 0%, green: 0%, blue: 100% }
yellow: { red: 100%, green: 100%, blue: 0% }
purple: { red: 100%, green: 0%, blue: 100% }
randomize: { effect: Randomize }
my_white_presets:
cold: { color_temperature: 153 mireds }
chilly: { color_temperature: 275 mireds }
luke: { color_temperature: 400 mireds }
warm: { color_temperature: 588 mireds
```
### Configuration variables:
* **name** (**Required**, string): The name of the light.
* **id** (*Optional*, ID): Manually specify the ID used for code generation. By providing an id,
you can reference the light from automation rules (e.g. to turn on the light when the power button
is tapped)
* **default_transition_length** (*Optional*, Time): The transition length to use when no transition
length is set in a light call. Defaults to 1s.
* **effects** (*Optional*, list): A list of
[light effects](https://esphome.io/components/light/index.html#light-effects) to use for this light.
* **presets** (*Optional*, dict): Used to define presets, that can be used from automations. See
[below](#light-presets) for detailed information.
* **on_brightness** (*Optional*, Action): An automation to perform when the brightness of the light
is modified.
* All other options from
[the base Light implementation](https://esphome.io/components/light/index.html#config-light),
except for options that handle color correction options like `gamma_correct` and `color_correct`.
These options are superceded by the fact that the light component has a fully customized light
model, that closely follows the light model of the original lamp's firmware.
### Light modes
The lamp supports multiple light modes. These are:
* **RGB light** (input: RGB + brightness > 1%)
* **White light** (input: Color Temperature + brightness > 1%)
* **Night light** (input: RGB or White light + brightness at 1%)
In the original firmware + Yeelight Home Assistant integration, the night light feature is
implemented through a switch component. The switch can be turned on to activate the night light
mode. In this ESPHome firmware, setting the brightness to its lowest value triggers the night light
mode. This makes things a lot easier to control.
It is possible to control the night light mode separately. An example of this can be found in the
[example.yaml](../example.yaml), in which holding the power button is bound to activating the night
light.
### `light.disco_on` Action
This action sets the state of the light immediately (i.e. without waiting for the next main loop
iteration), without saving the state to memory and without publishing the state change.
```yaml
on_...:
then:
- light.disco_on:
id: my_bedside_lamp
brightness: 80%
red: 70%
green: 0%
blue: 100%
```
The possible configuration options for this Action are the same as those for the standard
`light.turn_on` Action.
### `light.disco_off` Action
This action turns off the disco mode by restoring the state of the lamp to the last known state from
before using the disco mode.
```yaml
on_...:
then:
- light.disco_off:
id: my_bedside_lamp
```
### Light presets
The presets functionality was written with the original lamp firemware functionality in mind: the
user has two groups of presets available: one for RGB light presets and one for white light presets
(based on color temperature). The color button (the top one on the front panel) can be tapped to
switch to the next preset within the active preset group. The same button can be held for a little
while, to switch to the other preset group.
In your light configuration, you can mimic this behavior (in fact: it is done so in the
[example.yaml](../example.yaml)) by means of the presets system. This system consists of two parts:
* Defining presets
* Activating presets from automations
**Defining presets**
Presets can be configured in the `presets` option of the `light` configuration.
Presets are arranged in groups. You can define as little or as many groups as you like. The example
configuration uses two groups, but that is only to mimic the original behavior. If you only need one
group, then create one group. If you need ten, go ahead and knock yourself out.
The general structure of the presets configuration is:
```yaml
light:
presets:
group_1:
preset_1: ...
preset_2: ...
..
group_2:
preset_1: ...
preset_2: ...
..
..
```
*Note: Duplicate template names are ok, as long as they are within their own group. If you use
duplicate preset names within a single group, then the last preset will override the earlier
one(s).*
A preset can define one of the following:
* **RGB light**
* **red** (**Optional**, percentage): the red component of the RGB value (default = 0%).
* **green** (**Optional**, percentage): the green component of the RGB value (default = 0%).
* **blue** (**Optional**, percentage): the blue component of the RGB value (default = 0%).
* **brightness** (*Optional*, percentage): the brightness to use (default = current brightness).
* **transition_length** (*Optional*, time): the transition length to use.
* **White light**
* **color_temperature** (**Required**, mireds): the color temperature in mireds (range: "153 mireds" - "588 mireds")
* **brightness** (*Optional*, percentage): the brightness to use (default = current brightness).
* **transition_length** (*Optional*, time): the transition length to use.
* **Light effect**
* **effect** (**Required**, string): the name of a light effect to activate.
* **Brightness change only**
* **brightness** (**Required**, percentage): the brightness to use.
**Activating presets from automations**
Once presets have been configured, they can be activated using the `preset.activate` action. The
following options are available for this action:
* Switch to next preset group (and after the last, switch to the first):
```yaml
preset.activate:
next: group
```
* Switch to next preset within currentl preset group (and after the last,
switch to the first):
```yaml
preset.activate:
next: preset
---
* Activate a specific preset group by specifying the group's name:
```yaml
preset.activate:
group: rgb
```
* Activate a specific preset by specifying both the preset's name and group name:
```yaml
preset.activate:
group: white
preset: warm
```
Shorthand definitions are available for all these actions:
```yaml
preset.activate: next_group
preset.activate: next_preset
preset.activate: rgb
preset.activate: white.warm
```
**Handling of invalid input**
When a group or template is specified that does not exist, or if next group/preset is used while no
presets have been defined at all, then the action will be ignored and an error will be logged.
## Component: binary_sensor
Binary sensors can be added to the configuration for handling touch/release events for the front
panel. On touch, a binary_sensor will publish `True`, on release it will publish `False`. The
configuration of a binary_sensor determines what part of the front panel is involved in the touch
events.
```yaml
binary_sensor:
- platform: xiaomi_bslamp2
id: my_bedside_lamp_power_button
for: POWER_BUTTON
on_press:
then:
- light.toggle: my_bedside_lamp
```
For referencing the parts of the front panel, the following part identifiers are available:
* POWER_BUTTON (or its alias: POWER)
* COLOR_BUTTON (or its alias: COLOR)
* SLIDER
If personal taste dictates so, you can use lower case characters and spaces instead of underscores.
This means that for example "Power Button" and "power" would be valid identifiers for the power
button.
### Configuration variables:
* **name** (*Optional*, string): The name of the binary sensor. Setting a name will expose the
binary sensor as an entity in Home Assistant. If you do not need this, you can omit the name.
* **id** (*Optional*, ID): Manually specify the ID used for code generation. By providing an id,
you can reference the binary_sensor from automation rules (to retrieve the current state of the
binary_sensor).
* **for** (*Mandatory*, part identifier): This specifies to for part of the front panel the binary
sensor must report touch events.
* All other options from
[Binary Sensor](https://esphome.io/components/binary_sensor/index.html#config-binary-sensor).
## Component: sensor
The sensor component publishes touch events for the front panel slider. The published value
represents the level at which the slider was touched.
*Note: This sensor only reports the touched slider level. It cannot be used for detecting release
events. If you want to handle touch/release events for the slider, then you can make use of the
[binary_sensor](#component-binary_sensor) instead.*
```yaml
sensor:
- platform: xiaomi_bslamp2
- id: my_bedside_lamp_slider_level
range_from: 0.2
range_to: 0.9
on_value:
then:
- light.turn_on:
id: my_bedside_lamp
brightness: !lambda return x;
```
### Configuration variables:
* **name** (*Optional*, string): The name of the sensor. Setting a name will expose the sensor as an
entity in Home Assistant. If you do not need this, you can omit the name.
* **id** (*Optional*, ID): Manually specify the ID used for code generation. By providing an id,
you can reference the sensor from automation rules (e.g. to retrieve the current state of the
binary_sensor).
* **range_from** (*Optional*, float): By default, published values vary from the range 0.01 to 1.00,
in 20 steps. This option modifies the lower bound of the range.
* **range_to** (*Optional*, float): This option modifies the upper bound of the range.
* All other options from
[Sensor](https://esphome.io/components/sensor/index.html#config-sensor).
## Component: output
The (float) output component is linked to the front panel illumination + level indicator. Setting
this output (using the standard `output.set_level` action) to value 0.0 will turn off the frontpanel
illumination. Other values, up to 1.0, will turn on the illumination and will set the level indicator
to the requested level (in 10 steps).
```yaml
output:
- platform: xiaomi_bslamp2
id: my_bedside_lamp_front_panel_illumination
```
### Configuration variables:
* **id** (**Required**, ID): The id to use for this output component.
* All other options from [Output](https://esphome.io/components/output/index.html)
### Addressing the LEDs of the illumination individually
While the standard `output.set_level` action emulates the front panel illumination behavior
of the original device firmware, it is also possible to control all of the LEDs for this
illumination individually, in case you need some different behavior, e.g. leaving the
power button on at night, so the user can easily find it in the dark.
To address the LEDs, the following identifiers can be used in your YAML configuration:
* `POWER` : The power button illumination.
* `COLOR` : The color button illumination.
* `1`, `2`, .., `10` : The 10 LEDs on the slider, where LED `1` is closest to the
power button and LED `10` is closest to the color button.
* `ALL` : represents all of the available LEDs
* `NONE` : represents none of the available LEDs
#### `front_panel.set_leds` Action
This action turns on the provided LEDs, all other LEDs are turned off.
```yaml
on_...:
then:
- front_panel.set_leds:
leds:
- POWER
- COLOR
- 1
- 2
- 3
```
The `leds:` key can also be omitted here, making the following action calls
equivalent to the one above.
```yaml
on_...:
then:
- front_panel.set_leds:
- POWER
- COLOR
- 1
- 2
- 3
```
This can also be written as:
```yaml
on_...:
then:
- front_panel.set_leds: [ POWER, COLOR, 1, 2, 3 ]
```
If only one LED is specified, you are allowed to omit the list definition:
```yaml
on_...:
then:
- front_panel.set_leds: POWER
```
#### `front_panel.turn_on_leds` Action
This action turns on the provided LEDs, and leaves the rest of the LEDs as-is.
The LEDs to affect are specified in the same wat as above for `front_panel.set_leds`.
#### `front_panel.turn_off_leds` Action
This action turns off the provided LEDs, and leaves the rest of the LEDs as-is.
The LEDs to affect are specified in the same wat as above for `front_panel.set_leds`.
#### `front_panel.set_level` Action
This action works like the `output.set_level` action, but it only updates the
LEDs of the slider. The LEDs for the power and color button are left as-is.
```yaml
on_...:
then:
- front_panel.set_level: 0.5
```
#### `front_panel.update_leds` Action
The previous actions only modify the required state for the front panel LEDs.
Updating the actual state of the LEDs is done when the main loop for the
output component is run by ESPHome.
If you need the required state to be pushed to the LEDs immediately, regardless
the main loop, then this action can ben used to take care of this.
*Note: In most situations, you will not need to use this action explicitly
to make the LEDs update. Only use it when you are sure that this is required.*
```yaml
on_...:
then:
- front_panel.set_leds: POWER
- front_panel.update_leds:
```
## Component: text_sensor
The text sensor component publishes changes in the active [light mode](#light-modes). Possible
output values for this sensor are: "off", "rgb", "white" and "night".
### Configuration variables:
* **name** (*Optional*, string): The name of the text sensor. Setting a name will expose the text
sensor as an entity in Home Assistant. If you do not need this, you can omit the name.
* **id** (*Optional*, ID): Manually specify the ID used for code generation. By providing an id,
you can reference the text sensor from automation rules (to retrieve the current state of the
text_sensor).
* All other options from
[Text Sensor](https://esphome.io/components/text_sensor/index.html)
< [Installation guide](installation.md) | [Index](../README.md) | [Flashing guide](flashing.md) >

+ 287
- 0
doc_chinese/flashing.md View File

@ -0,0 +1,287 @@
< [Configuration guide](configuration.md) | [Index](../README.md) | [Technical details](technical_details.md) >
# Flashing guide
Table of contents:
* [Warning](#warning)
* [Tools needed](#tools-needed)
* [Opening the lamp, to expose the PCB](#opening-the-lamp-to-expose-the-pcb)
* [Solder wires to the board](#solder-wires-to-the-board)
* [Connect the wires to your serial to USB adapter](#connect-the-wires-to-your-serial-to-usb-adapter)
* [When you only have one GND pin on your USB Adapter](#when-you-only-have-one-gnd-pin-on-your-usb-adapter)
* [Make a backup of the current firmware](#make-a-backup-of-the-current-firmware)
* [How to restore the backed up firmware](#how-to-restore-the-backed-up-firmware)
* [Flash new ESPHome firmware](#flash-new-esphome-firmware)
* [Troubleshooting flash](#troubleshooting-flash)
## Warning
We have writen these instructions with care, but we will give absolutely no warranty. Perhaps you
will destroy your lamp and your computer.
## Tools needed
* Allen key (2mm, 5/64") or torx (T8) screw driver
* Soldering Iron
* A serial to USB adapter (for example FTDI) that can provide 3.3V RX/TX signals
* Some wires
* Optional: sticky tape, hot glue gun, magnifying glass
## Opening the lamp, to expose the PCB
*Tip: you can click on all images from below to view them in full size.*
Remove the rubber pads from the bottom of the lamp, to get access to 4 screws that attach the bottom
to the rest of the lamp.
<img src="../images/01_unboxed.jpg" width="200"><img src="../images/02_remove_rubber_pads.jpg" width="200">
Note that you don't have to remove these pads fully. Once you can access the screws, you've gone far
enough.
<img src="../images/03_bolts_overview.jpg" width="200">
Unbolt the 4 screws which were hidden under the rubber pads.
<img src="../images/04_remove_bolts.jpg" width="200"><img src="../images/05_bolts.jpg" width="200">
Detach the bottom from the rest of the lamp, exposing the PCB. This might take a bit of force. Just
pull it off bit by bit, until it pops loose.
<img src="../images/06_pull_off_the_bottom.jpg" width="200"><img src="../images/07_bottom_removed.jpg" width="200">
<img src="../images/08_board_exposed.jpg" width="400">
## Solder wires to the board
The wires will be connected to the debug pads that are shown in the following image.
<img src="../images/09_debug_pads_for_soldering.jpg" width="400">
Many of the serial to USB adapter have some header pins to which you can connect the wires of a
device (no soldering required). Therefore, it might be useful to use dupont wire. Cut off one end,
strip the wire, tin the wire and solder it to the board.
*Note: Whether to use male or female dupont wires depends on how you want to connect the serial
adapter. In this example, I have used male wires, so I could plug them into a breadbord.*
<img src="../images/10_stripped_dupont_wires.jpg" width="200">
Solder the wires to the `RX`, `TX`, `GND` and `GPIO0` debug pads.
Beware not to use too much solder on the GPIO0 pad, because that might flow onto the pad that is right
next to it, permanently putting the device in flash mode as a result.
*Note: The board has a debug pad that exposes 3.3V. Do not use this pad to power the board from your
serial adapter. Always power the lamp using its own power supply.*
A few tips:
- Depending on the quality of your eyes, you might want to use a magnifying glass for the soldering
work. Use one that is mounted on a stand, or you will quickly be left wishing that you could grow
a third arm.
- You could use some sticky tape to fixate the cables before soldering.
- When you want to keep the wires attached after flashing the new firmware (e.g. for serial logging
or for future firmware flashing), then you might want to apply some hot glue to fixate the wires.
This prevents the wires from breaking off, due to excessive movement.
<img src="../images/11_soldered_wires.jpg" width="200"><img src="../images/12_optional_hot_glue.jpg" width="200">
## Connect the wires to your serial to USB adapter
Make sure that your adapter uses 3.3V for the RX/TX pins that you will connect to the lamp. Some of
these adapters allow you to switch between 3.3V and 5V using a switch or a jumper. Do not use an
adapter that only provides 5V output. Reason for this, is that the ESP32 chip works at 3.3V. I have
seen the chips accept 5V serial input (I did flash the lamp successfully like that), but I am not
sure if they are actually 5V tolerant. Better safe than sorry in such case!
The wires must be connected as follows:
| Soldering point| Serial USB Adapter name |
| -------------- |:------------------------:|
| GND | GND |
| TX | RX |
| RX | TX (3.3V) |
| 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. The rest of this guide
will show this method.
[View example by @mmakaay](../images/13_connect_to_serial_to_usb_adapter.jpg).
- **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. Some example implementations:
[a crude one by @mmakaay](../images/13_connect_to_serial_with_button.jpg),
[one by @edwinschoonhoven](../images/13_connect_to_serial_with_button_alternative.jpg) and
[one by @mmakaay, inspired by Erwin's](../images/13_connect_to_serial_with_button_alternative2.jpg).
- **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.
- **Temporarily solder 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.
[View example by @erwinschoonhoven](../images/13_connect_to_serial_with_soldered_gnd.jpg).
In the following images, you will see the first solution, using a breadboard.
<img src="../images/13_connect_to_serial_to_usb_adapter.jpg" width="400">
In close up:
<img src="../images/14_connect_to_serial_to_usb_adapter_close_up.jpg" width="400">
You can now connect the serial to USB adapter to you computer. Pay special attention to the
cross-over of the TX/RX pair (TX connects to RX and vice versa). Start the
[esphome-flasher tool](https://github.com/esphome/esphome-flasher) and select the COM port to use.
Then click on "View logs".
Now, plug in the lamp's power supply to boot up the lamp.
<img src="../images/15_power_up_for_flashing.jpg" width="400">
Because GPIO0 is connected to GND, the device should start up in flashing mode. If all went well,
the log output in esphome-flasher looks somewhat like this:
<img src="../images/16_serial_showing_download_mode.png" width="400">
## 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 back 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.
## How to 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 while esptool tool is verifying that
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 strongly recommend using the
[esphome-flasher](https://github.com/esphome/esphome-flasher) tool. This is a very easy to use GUI
utility app for flashing ESPHome devices and for viewing serial console logging.
- In the app, select the COM port of your serial adapter.
- Then 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 all went well, the final log output in esphome-flasher looks somewhat like this:
<img src="../images/17_flash_ready.png" width="400">
If you want to flash with esptool, you can use the following command.
*Note: unless you know exactly what you're doing with esptool here, I recommend to use the
esphome-flasher instead.*
```
python esptool.py --chip esp32 -p /dev/ttyUSB0 --baud 115200 \
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 firmware.bin
```
The required .bin files can be found in the following locations:
- **bootloader_dout_40m.bin**: [from arduino-esp32 package](https://github.com/mmakaay/arduino-esp32-unicore-no-mac-crc/blob/v1.0.6/tools/sdk/bin/bootloader_dout_40m.bin) in `tools/sdk/bin/`
- **partitions.bin**: from `<config dir>/<device name>/.pioenvs/<device name>/partitions.bin`
- **boot_app0.bin**: [from arduino-esp32 package](https://github.com/mmakaay/arduino-esp32-unicore-no-mac-crc/blob/v1.0.6/tools/partitions/boot_app0.bin) in `tools/partitions/`
- **firmware.bin**: from `<config dir>/<device name>/.pioenvs/<device name>/firmware.bin`
After flashing, power down the lamp, disconnect `GPIO0` from GND and reconnect the power to boot
into the new ESPHome firmware.
<img src="../images/18_disconnect_GPIO0.jpg" width="200">
The lamp should now be operational using the new firmware.
<img src="../images/19_test_run.jpg" width="200">
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.
Because I want to keep them around for future use, I tuck them away, making sure that the connectors
don't touch each other or the board.
<img src="../images/20_tuck_away_wires.jpg" width="200">
The bottom cover can now be put back on. The lamp is ready for use.
<img src="../images/21_reassemble_and_enjoy.jpg" width="200">
## 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.
< [Configuration guide](configuration.md) | [Index](../README.md) | [Technical details](technical_details.md) >

+ 38
- 0
doc_chinese/installation.md View File

@ -0,0 +1,38 @@
< [Why custom firmware?](why_custom_firmware.md) | [Index](../README.md) | [Configuration guide](configuration.md) >
# Installation guide
The code must be compiled into a firmware using ESPHome 2021.10.0 or later. 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 as an add-on). For information on this, please refer to the
documentation on the [ESPHome website](https://esphome.io).
The component code is distributed directly from GitHub. You will not have to download and install
the code manually. This leverages the [external components](https://esphome.io/components/external_components.html)
feature.
Before you can compile the firmware, you will have to create the YAML configuration file for your
device. You can take the [`example.yaml`](../example.yaml) from this repository as a starting point, and
modify that one to your needs. Detailed information about the YAML configuration options can be
found in the [Configuration guide](configuration.md).
After these steps you can let ESPHome compile your firmware (`firmware.bin`) file. This firmware
can then be flashed onto the device.
**Note**: During compilation you might see some warning messages from ESPHome, telling you:
```
WARNING GPIO4 is a Strapping PIN and should be avoided.
...
WARNING GPIO2 is a Strapping PIN and should be avoided.
```
You can safely ignore these type of warnings. GPIO4 and GPIO2 are hard-wired in the lamp's PCB.
The way in which the firmware uses these pins does not pose any problems for 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 [the flashing guide](flashing.md) for hints on opening up the device and flashing its firmware
using the serial interface.
< [Why custom firmware?](why_custom_firmware.md) | [Index](../README.md) | [Configuration guide](configuration.md) >

+ 37
- 0
doc_chinese/release_plan.md View File

@ -0,0 +1,37 @@
# Release plan
All development is done in the `dev` branch. Once the development branch is
ready for a new production release, the following steps are followed:
**Update the CHANGELOG.md**
Make sure all notable changes are recorded in the changelog.
**Update ESPHome version information**
The minimum ESPHome version requirement must be documented correctly in the following files:
* doc/installation.md (at the start of the file)
* README.md (at the start of the quick start guide)
* CHANGELOG.md (at the start of the log for the released version)
**Create version release branch**
Branch `dev` to a `release/<version>` branch, e.g. `release/2021.10.0`.
```
$ git checkout dev
$ git checkout -b release/2021.10.0
```
**Update project version information**
The version of this project (e.g. `2021.10.0`) must be updated in:
* `example.yaml` (the `ref:` for the bslamp2 configuration package)
* `packages/core.yaml` (the `ref:` for the external component)
**Push the release to GitHub**
```
$ git push --set-upstream origin release/2021.10.0
```

+ 20
- 0
doc_chinese/sponsoring.md View File

@ -0,0 +1,20 @@
< [Technical details](technical_details.md) | [Index](../README.md)
# Sponsoring the project
All development on this firmware is done for the greater good of mankind. You can use it for free.
However, if you do feel the uncontrollable urge to contribute financially to the project, you can do
so through [this PayPal link](https://www.paypal.com/paypalme/bedsidelamp2).
This account is used for acquiring hardware and software licenses that I use for my open source
development. Specific hardware that I bought for this project were:
* An extra lamp for development and testing, so I don't annoy my wife with buggy deployements ;-)
* A dedicated serial to USB adapter, connected to the development lamp.
* a simple 8 port logic analyzer that helped me with reverse engineering the I2C protocol of the
front panel.
* Various wires and buttons.
* An Arduino Uno R3, to [help out somebody in the community forums with
flashing the lamp using the Arduino](https://community.home-assistant.io/t/hacking-yeelight-fw-enabling-lan-control/284406/214?u=mmakaay).
< [Technical details](technical_details.md) | [Index](../README.md)

+ 381
- 0
doc_chinese/technical_details.md View File

@ -0,0 +1,381 @@
< [Flashing guide](flashing.md) | [Index](../README.md) | [Sponsoring](sponsoring.md) >
# Technical details
In this section, you can find some of the information that was gathered during the reverse
engineering of the Bedside Lamp 2 hardware.
Table of contents:
* [High level overview](#high-level-overview)
* [ESP32 pinout](#esp32-pinout)
* [Front panel](#front-panel)
* [Build requirements](#build-requirements)
* [Original firmware](#original-firmware)
## High level overview
No documentation is complete without some ASCII art schematics.
```
RX/TX/GND for
12V power supply flashing and logs
| |
v | Front panel
+---------------+ +---------------+ .---.
| Power supply |---- 3.3V -.----->| ESP-WROOM-32D |<- I2C ->| O | -- color
+---------------+ \ | single core | | | button
| \ | 4 MB flash |<- IRQ --| | |
12V \ +---------------+ | | |
| `-------|------------------->| | | -- slider
v | | | |
+---------------+ | | | |
| RGB and white |<---- RGBW + master ---+ | | power
| LED circuitry | PWM on/off | O | -- button
+---------------+ `---`
```
The LED circuitry provides two light modes:
* Colored RGB light;
* Warm to cool white light.
The front panel of the device contains a two touch buttons (power on/off and color selection) and a
touch slider (for setting the brightness level). This panel is lit when the device is turned on. The
light behind the slider will represent the actual brightness setting of the device.
## ESP32 pinout
In the following image, you can find the pinout as used for the ESP32:
<img src="../images/hardware/ESP32_pinout.jpg" width="600">
Here's an overview of all exposed pins of the chip, starting at the GND + 3.3V pins, and going
anti-clockwise. The table shows not only the functions of the pins that are actually in use by the
lamp's circuitry, but also the pins that are not in use and their possible use.
| PIN | GPIO# | Function | Description | Possible use |
|------|--------|-----------|--------------------------------|--------------|
| GND | | Ground | Connected to ground | - |
| 3.3V | | Power | Power supply input | - |
| 9 | | Reset | Can be pulled to GND to reset | - |
| 5 | GPIO36 | - | | IN |
| 8 | GPIO39 | - | | IN |
| 10 | GPIO34 | - | | IN |
| 11 | GPIO35 | - | | IN |
| 12 | GPIO32 | - | | IN/OUT |
| 13 | GPIO33 | LEDs | LEDs, master switch 1 | - |
| 14 | GPIO25 | ??? | 10k pull up, unknown function | IN/OUT (1) |
| 15 | GPIO26 | - | | IN/OUT |
| 16 | GPIO27 | - | | IN/OUT |
| 17 | GPIO14 | LEDs | LEDs, green PWM channel | - |
| 18 | GPIO12 | LEDs | LEDs, white PWM channel | - |
| GND | | Ground | Connected to ground | - |
| 20 | GPIO13 | LEDs | LEDs, red PWM channel | - |
| 28 | GPIO9 | SPI | SPI flash memory | - |
| 29 | GPIO10 | SPI | SPI flash memory | - |
| 30 | GPIO11 | SPI | SPI flash memory | - |
| 31 | GPIO6 | SPI | SPI flash memory | - |
| 32 | GPIO7 | SPI | SPI flash memory | - |
| 33 | GPIO8 | SPI | SPI flash memory | - |
| 21 | GPIO15 | - | | IN/OUT (2) |
| 22 | GPIO2 | - | Debug pad, no function | IN/OUT (3) |
| 23 | GPIO0 | Boot mode | Pull to GND for flashing mode | - |
| 24 | GPIO4 | LEDs | LEDs, master switch 2 | - |
| 25 | GPIO16 | Front pnl | Front panel interrupt | - |
| 27 | GPIO17 | EEPROM | EEPROM I2C SDA (4) | - |
| 34 | GPIO5 | LEDs | LEDs, blue PWM channel | - |
| 35 | GPIO18 | EEPROM | EEPROM I2C CLK (4) | - |
| 38 | GPIO19 | Front pnl | Front panel I2C SCL | - |
| N/C | | | | |
| 42 | GPIO21 | Front pnl | Front panel I2C SDA | - |
| 40 | GPIO3 | Serial | Debug pad, RX (flashing, logs) | - |
| 41 | GPIO1 | Serial | Debug pad, TX (flashing, logs) | - |
| 39 | GPIO22 | - | | IN/OUT |
| 36 | GPIO23 | - | | IN/OUT |
| GND | | Ground | Connected to ground | - |
1. GPIO25 is connected to a 10k pull up resistor. This suggests that it might have some function in
the lamp, but I have not found that function yet. If you find the actual use for this pin, or
find that you can indeed repurpose it, then please let me know.
1. Beware that GPIO15 outputs a PWM signal at boot. This might make the pin less useful for your use
case.
1. Often, GPIO2 is used for an on-board LED. Here, it is only connected to the debug pad. The pin is
usable for I/O (I tested it), which is great because of the easy access of the debug pad. GPIO2
might only be used for testing purposes in the original firmware.
1. The connected IC, using I2C address 0x10, looks a lot like an EEPROM, but this has yet to be
confirmed. It uses a decicated I2C bus, separate from the I2C bus of the front panel.
[This picture](../images/hardware/IC_on_I2C_GPIO1718.jpg) shows the IC.
For more information on the use of pins on the ESP32 chip, please check out
this [ESP32 pinout reference information](https://randomnerdtutorials.com/esp32-pinout-reference-gpios/).
## Front panel
<img src="../images/hardware/front_panel.jpg" width="150">
The front panel is a stand-alone component, with its own control chip (KungFu KF8TS2716).
Communication between the ESP32 and the front panel is done using:
- **An I2C bus**
- the front panel is the I2C slave, the ESP32 is the I2C master
(pardon the standard terminology, I am aware of the controversy)
- the front panel device ID is 0x2C
- SDA is connected to ESP32 pin GPIO21
- SCL is connected to ESP32 pin GPIO19
- **An interrupt data line to signal the ESP32 about new events**
- this line is connected to ESP32 pin GPIO16
- the default state is HIGH
- line is pulled LOW for at least 6 ms when a new event is available
Commands can be written to and data can be read from the front panel component using I2C. The I2C
protocol is fairly simple. All read and write operations uses 6 bytes of data. No register selection
is done before reading or writing.
The interrupt data line is used by the front panel, to signal the ESP32 that a new button or slider
event is available. Further details on this can be found below.
**Connection to the main board**
The front panel is connected to the main board using a flat cable. The picture below shows the
connector on the main board, including the functions of the cable pins:
<img src="../images/hardware/front_panel_flat_cable_connection.jpg" width="400">
**Writing commands to the front panel**
Commands can be written to the front panel at any time.
The commands that are used by the original firmware are these:
| Command | Byte sequence to send |
|-----------------|-----------------------|
| TURN PANEL ON | 02 03 5E 00 64 00 00 |
| TURN PANEL OFF | 02 03 0C 00 64 00 00 |
| SET LEVEL 1 | 02 03 5E 00 64 00 00 |
| SET LEVEL 2 | 02 03 5F 00 64 00 00 |
| SET LEVEL 3 | 02 03 5F 80 64 00 00 |
| SET LEVEL 4 | 02 03 5F C0 64 00 00 |
| SET LEVEL 5 | 02 03 5F E0 64 00 00 |
| SET LEVEL 6 | 02 03 5F F0 64 00 00 |
| SET LEVEL 7 | 02 03 5F F8 64 00 00 |
| SET LEVEL 8 | 02 03 5F FC 64 00 00 |
| SET LEVEL 9 | 02 03 5F FE 64 00 00 |
| SET LEVEL 10 | 02 03 5F FF 64 00 00 |
| READY FOR EVENT | 01 00 00 00 00 00 01 |
*Note: The `READY FOR EVENT` command is only used when a new event is provided by the front panel.
Information about this command can be found in the next section.*
Further experimentation has uncovered that the LEDs of the front panel can be controlled
individually. The original firmware does not use this feature, but I built support for it
into the custom firmware, because it opens up some nice possibilities.
How this works, is that the general format of the "set LEDs" command is: `02 03 XX XX 64 00 00`.
The LEDs to enable are specified using the `XX XX` part. This is a 16 bit value, which can be
constructed by bitwise OR-ing the following LED bit values:
| LED to enable | Bit pattern |
|---------------|-------------------|
| POWER | 01001100 00000000 |
| COLOR | 00011100 00000000 |
| LED 1 | 00001110 00000000 |
| LED 2 | 00001101 00000000 |
| LED 3 | 00001100 10000000 |
| LED 4 | 00001100 01000000 |
| LED 5 | 00001100 00100000 |
| LED 6 | 00001100 00010000 |
| LED 7 | 00001100 00001000 |
| LED 8 | 00001100 00000100 |
| LED 9 | 00001100 00000010 |
| LED 10 | 00001100 00000001 |
LED 1 is the one closest to the power button.
LED 10 is the one closest to the color button.
**Reading events from the front panel**
The types of events that can occur can be summarized as:
- Touch or release the power button
- Touch or release the color button
- Touch or release the slider at a certain level
Because the front panel is an I2C slave device, it cannot contact the ESP32 via I2C. Only an I2C
master device can initiate communication. Therefore, when the front panel has a new event available,
it will pull down the interrupt line for a short period of time, to signal the ESP32 about this new
event.
*Note that the ESP32 needs to poll the interrupt line at least at 667 Hz to be able to trustworthy
detect the 6 ms signal. Unfortunately, the interrupt line does not wait for the ESP32 to respond to
its signalling. The best way to handle signals from this line, is to use an actual interrupt
handler.*
After detecting this signal, the ESP32 must first write the "READY FOR EVENT" command (`01 00 00 00
00 00 01`) via I2C to the front panel.
After the front panel has ACK'ed this command, the ESP32 can read 6 bytes, which will represent the
event that occurred.
Here's the mapping for the events and their corresponding byte sequences:
| | Touch event | Release event |
|-----------------|----------------------|----------------------|
| POWER BUTTON | 04 04 01 00 01 01 03 | 04 04 01 00 01 02 04 |
| COLOR BUTTON | 04 04 01 00 02 01 04 | 04 04 01 00 02 02 05 |
| SLIDER LEVEL 1 | 04 04 01 00 03 16 1A | 04 04 01 00 04 16 1B |
| SLIDER LEVEL 2 | 04 04 01 00 03 15 19 | 04 04 01 00 04 15 1A |
| SLIDER LEVEL 3 | 04 04 01 00 03 14 18 | 04 04 01 00 04 14 19 |
| SLIDER LEVEL 4 | 04 04 01 00 03 13 17 | 04 04 01 00 04 13 18 |
| SLIDER LEVEL 5 | 04 04 01 00 03 12 16 | 04 04 01 00 04 12 17 |
| SLIDER LEVEL 6 | 04 04 01 00 03 11 15 | 04 04 01 00 04 11 16 |
| SLIDER LEVEL 7 | 04 04 01 00 03 10 14 | 04 04 01 00 04 10 15 |
| SLIDER LEVEL 8 | 04 04 01 00 03 0F 13 | 04 04 01 00 04 0F 14 |
| SLIDER LEVEL 9 | 04 04 01 00 03 0E 12 | 04 04 01 00 04 0E 13 |
| SLIDER LEVEL 10 | 04 04 01 00 03 0D 11 | 04 04 01 00 04 0D 12 |
| SLIDER LEVEL 11 | 04 04 01 00 03 0C 10 | 04 04 01 00 04 0C 11 |
| SLIDER LEVEL 12 | 04 04 01 00 03 0B 0F | 04 04 01 00 04 0B 10 |
| SLIDER LEVEL 13 | 04 04 01 00 03 0A 0E | 04 04 01 00 04 0A 0F |
| SLIDER LEVEL 14 | 04 04 01 00 03 09 0D | 04 04 01 00 04 09 0E |
| SLIDER LEVEL 15 | 04 04 01 00 03 08 0C | 04 04 01 00 04 08 0D |
| SLIDER LEVEL 16 | 04 04 01 00 03 07 0B | 04 04 01 00 04 07 0C |
| SLIDER LEVEL 17 | 04 04 01 00 03 06 0A | 04 04 01 00 04 06 0B |
| SLIDER LEVEL 18 | 04 04 01 00 03 05 09 | 04 04 01 00 04 05 0A |
| SLIDER LEVEL 19 | 04 04 01 00 03 04 08 | 04 04 01 00 04 04 09 |
| SLIDER LEVEL 20 | 04 04 01 00 03 03 07 | 04 04 01 00 04 03 08 |
| SLIDER LEVEL 21 | 04 04 01 00 03 02 06 | 04 04 01 00 04 02 07 |
| SLIDER LEVEL 22 | 04 04 01 00 03 01 05 | 04 04 01 00 04 01 06 |
**Behavior when more events come in than can be handled**
The front panel does not queue events. When a new event occurs, before the previous event has be
read by the ESP32, the new event will replace the old event and a new signal is sent over the
interrupt line.
The ESP32 can read the last event multiple times. It will not be cleared by the front panel after
reading it.
## Build requirements
The ESP-WROOM-32D that is used for this lamp (and for various other Xiaomi devices), contains a
single core CPU, even though the data sheet for ESP-WROOM-32D specifies a dual core CPU. Therefore,
when flashing the device with a generic ESP32 build, you will end up with the following boot error:
```
E (459) cpu_start: Running on single core chip, but application is built with dual core support.
E (459) cpu_start: Please enable CONFIG_FREERTOS_UNICORE option in menuconfig.
```
Another issue with a lot of these devices, is that the MAC address that is burnt into EFUSE does not
match the CRC checksum that is also burnt into EFUSE. Using a generic ESP32 build, you will end up
with the boot error:
```
Base MAC address from BLK0 of EFUSE CRC error
```
For these reasons, you must build the firmware using a taylored version of arduino-esp32.
You can make use of the version [created by @pauln](https://github.com/pauln/arduino-esp32)
or the version [created by @mmakaay](https://github.com/mmakaay/arduino-esp32-unicore-no-mac-crc).
To make use of one of these in an ESPHome build, you'll have to provide a platform package
definition for the PlatformIO build. Here's an example configuration that will work for these Xiaomi
devices:
```yaml
esphome:
name: my_device_name
platform: ESP32
board: esp32doit-devkit-v1
platformio_options:
platform: espressif32@3.2.0
platform_packages: |-
framework-arduinoespressif32 @ https://github.com/mmakaay/arduino-esp32-unicore-no-mac-crc
```
If you want to build your own platform package, then you can checkout
the build scripts [by @mmakaay here](https://github.com/mmakaay/arduino-esp32-unicore-no-mac-crc-builder).
## Original firmware
Below, I have gathered some of the interesting boot messages from the original firmware. These
messages are logged via the serial interface.
**SPI Flash memory:**
```
boot: SPI Flash RID : 0xB20B4
boot: SPI Flash MF : 0xB4
boot: SPI Flash ID : 0x200B
boot: SPI Speed : 40MHz
boot: SPI Mode : DIO
boot: SPI Flash Size : 4MB
```
**Partition table:**
```
boot: Partition Table:
boot: ## Label Usage Type ST Offset Length
boot: 0 nvs WiFi data 01 02 00009000 00004000
boot: 1 otadata OTA data 01 00 0000d000 00002000
boot: 2 phy_init RF data 01 01 0000f000 00001000
boot: 3 miio_fw1 OTA app 00 10 00010000 001e0000
boot: 4 miio_fw2 OTA app 00 11 001f0000 001e0000
boot: 5 test test app 00 20 003d0000 00013000
boot: 6 mfi_p Unknown data 01 82 003e3000 00001000
boot: 7 factory_nvs WiFi data 01 02 003e4000 00004000
boot: 8 coredump Unknown data 01 03 003e8000 00010000
boot: 9 minvs Unknown data 01 fe 003f8000 00004000
boot: End of partition table
```
**MIIO initialization:**
```
_| _| _|_|_| _|_|_| _|_|
_|_| _|_| _| _| _| _|
_| _| _| _| _| _| _|
_| _| _| _| _| _|
_| _| _|_|_| _|_|_| _|_|
08:00:00.200 [I] did=332985470 hostname=MiBedsideLamp2-7651
JENKINS BUILD NUMBER: N/A
BUILD TIME: Sep 5 2019,07:12:39
BUILT BY: N/A
MIIO APP VER: 2.0.6_0030
Setup ID: 95XJ
Getting setup info from factory NVS
MIIO MCU VER:
MIIO DID: *********
MIIO WIFI MAC: ************
MIIO MODEL: yeelink.light.bslamp2
ARCH TYPE: esp32,0x0000a601
ARCH VER: d178b9b
```
**Network initialized:**
```
[20:27:05]08:00:04.180 [I] miio_net: Wifi station connected
[20:27:05]Registering HomeKit web handlers
[20:27:05]Announcing _hap._tcp mDNS service
```
**Phoning home to the Mijia cloud:**
```
ots: httpdns resolve start failed, -12 (ots_cloud_host_update,850)
otu: Opened.
ots: de.ots.io.mi.com resolved to 3.126.247.75.
ots: ots connect 3.126.247.75::443...
tls: connect to server Mijia Cloud, domain is 3.126.247.75, port is 443.
tls: timeout[100]! mbedtls_ssl_handshake returned -0x6800 (d0_tls_open,369)
tls: timeout[200]! mbedtls_ssl_handshake returned -0x6800 (d0_tls_open,369)
tls: timeout[300]! mbedtls_ssl_handshake returned -0x6800 (d0_tls_open,369)
tls: timeout[400]! mbedtls_ssl_handshake returned -0x6800 (d0_tls_open,369)
ots: Connected.
```
< [Flashing guide](flashing.md) | [Index](../README.md) | [Sponsoring](sponsoring.md) >

+ 73
- 0
doc_chinese/test_plan.md View File

@ -0,0 +1,73 @@
# Test plan
This is the test plan that I follow for every release. I use it to ensure that no regression has
been introduced.
## Step 1: Preparation - build and flash the firmware
* Use the latest stable release for ESPHome (to make sure that my code builds and works with that
release). In my clone I make sure that I checked out the master branch and that it's up-to-date
with the origin.
* Remove the cached framework package:
`/bin/rm -fR ~/.platformio/packages/framework-arduinoespressif32`
* Copy [`example.yaml`](../example.yaml) to a clean build directory, and update the first two sections for the
local setup (substitutions, wifi, api, ota).
* Use `esphome example.yaml compile` to build the code.
* Upload this code to the lamp.
## Step 2: Perform the tests
* Touch the power button --> the light must turn on.
* Touch the power button again --> the light must turn off.
* Touch the slider at any level --> the light must turn on, using the level at which the slider was
touched as the brightness. The front panel illumination is turned on and shows the brightness
level.
* Touch the slider at various points and touch the slider while moving your finger up and down -->
the brightness of the light and the brightness level on the front panel must follow the touches.
* Touch and hold the power button --> the light must go into "night light" mode. This means that it
will become very dim. The front panel illumination must be turned off.
* Touch the slider at a random level --> the light must go back to its normal brightness levels and
the front panel illumination must be turned on again.
* Touch the color button a few times in a row --> the light must loop through the various preset
light colors.
* Touch and hold the color button --> the light must switch to a different preset group. There are
two groups: one with rgb colors and one with white light colors, and holding the color button will
switch between these two.
* Touch the color button to select a light color, long touch it to switch to the other preset group,
then long touch again to switch the preset group again -> the lamp must remember what light colors
were active within the preset groups. If the red preset was selected, you switch to the white
light group, select a different white preset and then go back to the rgb presets, then the light
must become red again.
* Go to Home Assistant and check:
* if you can turn on/off the lamp
* if you can select colors from the RGB color model
* if you can select colors from the Color Temperature model
* if you can set the brightness of the lamp
* if selecting the lowest possible brightness results in the lamp
switching to "night light" mode
* if a transition from off to on with a long transition time works (e.g. 10s)
* if a transition from on to off with a long transition time works
* if a transition from night light to some bright light (e.g. 10s) can be
interrupted by a transition back to night light (e.g. after 5 seconds),
resulting in a transition back (not an instant drop to night light)
## Step 3: Release the new version
Only after performing these tests successfully, the new version can be released.
Release steps are documented in [`releaseplan.md`](releaseplan.md).

+ 123
- 0
doc_chinese/upgrading_to_2021.10.0.md View File

@ -0,0 +1,123 @@
# Upgrading to version 2021.10.0
Quite a few things have been changed in order to make the Xiaomi Bedside Lamp 2 firmware code compatible with
ESPHome version 2021.10.0. As a result, configuration changes are needed to make the configuration work with
the new code.
There are basically two ways in which you can upgrade:
1. Start a new configuration
2. Upgrade your existing configuration
## 1. Start a new configuration
*This is definitely the simplest way*.
Copy the new `example.yaml` configuration file from the GitHub repository and start a new configuration based
on that. When this configuration is working, you can extend your configuration to tweak the configuration to
your needs.
## 2. Upgrade your existing configuration
If you have done extensive customization, it might be easier to upgrade your existing configuration. Below
you find a list of changse that have to be applied, and that should get your configuration ready for 2021.10.0.
**Setup the following substitutions in your configuration file:**
```yaml
substitutions:
name: bedside-lamp
friendly_name: Bedside Lamp
light_name: ${friendly_name} RGBWW Light
light_mode_text_sensor_name: ${friendly_name} Light Mode
default_transition_length: 800ms
```
Other substitutions are not in use anymore, so you can delete them.
**Modify the existing `external_components:` configuration to:**
```yaml
external_components:
- source:
type: git
url: https://github.com/mmakaay/esphome-xiaomi_bslamp2
ref: release/2021.10.0
refresh: 60s
```
**Add the new core configuration package:**
```yaml
packages:
bslamp2:
url: https://github.com/mmakaay/esphome-xiaomi_bslamp2
ref: release/2021.10.0
files:
- packages/core.yaml
refresh: 0s
```
You can omit the ones that represent the required value already.
**Fully remove the existing `esphome:` configuration section**
Remove the following block from your configuration. The `core.yaml` configuration
package provides the required configuration, so you don't need it in your
configuration file anymore.
```yaml
esphome:
name: ${name}
...
etc.
```
**Modfy all instances of id's from a variable to a string value:**
- `${id_light}` -> `my_light`
- `${id_front_panel_illumination}` -> `my_front_panel_illumination`
- `${id_light_mode}` -> `my_light_mode`
- `${id_power_button}` -> `my_power_button`
- `${id_color_button}` -> `my_color_button`
- `${id_slider_level}` -> `my_slider_level`
These are the identifiers that I will be using from now on in the configuration
packages as well. By using these identifiers in all places, it will be easy to
distribute configuration packages that can be added to your configuration.
**Fully remove the front panel illumination output from the config**
This configuration is already being setup as part of the `core.yaml` configuration package.
When not removing it, you would get an error about the component being redefined. So simply
remove this block from your configuration:
```yaml
output:
- platform: xiaomi_bslamp2
id: my_front_panel_illumination
```
**Optionally, modify the the name of the light component**
For the name of the light, you can replace `${friendly_name} RGBWW Light` with
the new `${light_name}` substitution variable.
```yaml
light:
- platform: xiaomi_bslamp2
id: my_light
name: ${light_name}
...
```
** Optionally, modify the name of the text sensor**
Likewise, you can change the text sensor that publishes the current light mode as text.
The name can be changed from `${fiendly_name} Light Mode` to `${light_mode_text_sensor_name}`.
```yaml
text_sensor:
- platform: xiaomi_bslamp2
id: my_light_mode
name: ${light_mode_text_sensor_name}
```

+ 35
- 0
doc_chinese/why_custom_firmware.md View File

@ -0,0 +1,35 @@
[Index](../README.md) | [Installation guide](installation.md) >
# 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
[Index](../README.md) | [Installation guide](installation.md) >

Loading…
Cancel
Save