diff --git a/doc_chinese/configuration.md b/doc_chinese/configuration.md new file mode 100644 index 0000000..6524dbc --- /dev/null +++ b/doc_chinese/configuration.md @@ -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) > diff --git a/doc_chinese/flashing.md b/doc_chinese/flashing.md new file mode 100644 index 0000000..faa25a4 --- /dev/null +++ b/doc_chinese/flashing.md @@ -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. + + + +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. + + + +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. + + + + + + +## Solder wires to the board + +The wires will be connected to the debug pads that are shown in the following image. + + + +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.* + + + +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. + + + + +## 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. + + + +In close up: + + + +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. + + + +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: + + + + +## 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: + + + +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 `//.pioenvs//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 `//.pioenvs//firmware.bin` + +After flashing, power down the lamp, disconnect `GPIO0` from GND and reconnect the power to boot +into the new ESPHome firmware. + + + +The lamp should now be operational using the new 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. + +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. + + + +The bottom cover can now be put back on. The lamp is ready for use. + + + + +## 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) > diff --git a/doc_chinese/installation.md b/doc_chinese/installation.md new file mode 100644 index 0000000..0e42d65 --- /dev/null +++ b/doc_chinese/installation.md @@ -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) > diff --git a/doc_chinese/release_plan.md b/doc_chinese/release_plan.md new file mode 100644 index 0000000..b707940 --- /dev/null +++ b/doc_chinese/release_plan.md @@ -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/` 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 +``` diff --git a/doc_chinese/sponsoring.md b/doc_chinese/sponsoring.md new file mode 100644 index 0000000..9c3dfbb --- /dev/null +++ b/doc_chinese/sponsoring.md @@ -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) diff --git a/doc_chinese/technical_details.md b/doc_chinese/technical_details.md new file mode 100644 index 0000000..4603b1a --- /dev/null +++ b/doc_chinese/technical_details.md @@ -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: + + + +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 + + + +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: + + + +**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) > diff --git a/doc_chinese/test_plan.md b/doc_chinese/test_plan.md new file mode 100644 index 0000000..3df5e7d --- /dev/null +++ b/doc_chinese/test_plan.md @@ -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). diff --git a/doc_chinese/upgrading_to_2021.10.0.md b/doc_chinese/upgrading_to_2021.10.0.md new file mode 100644 index 0000000..9ab7960 --- /dev/null +++ b/doc_chinese/upgrading_to_2021.10.0.md @@ -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} +``` diff --git a/doc_chinese/why_custom_firmware.md b/doc_chinese/why_custom_firmware.md new file mode 100644 index 0000000..f707e40 --- /dev/null +++ b/doc_chinese/why_custom_firmware.md @@ -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) >