Update: 06.02.2025
ESP Home Config:
substitutions:
device_name: "xiaomi-smart-kettle-2-pro"
friendly_name: "Xiaomi Smart Kettle 2 Pro"
esphome:
name: ${device_name}
friendly_name: ${friendly_name}
comment: ''
esp32:
board: esp32doit-devkit-v1
framework:
type: esp-idf # Suggest using the ESP-IDF Framework. Changing from 'arduino' to 'esp-idf' needs a cabled flash to correct partitions
version: recommended
sdkconfig_options:
CONFIG_FREERTOS_UNICORE: y
advanced:
ignore_efuse_mac_crc: true
ignore_efuse_custom_mac: true #added in 2024-11 as a fix https://community.home-assistant.io/t/xiaomi-mi-led-desk-lamp-1s-error-integration/787346
logger:
level: DEBUG
api:
encryption:
key: !secret api_encryption_key
ota:
- platform: esphome
id: ota_password
password: !secret ota_password
safe_mode:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: ${device_name}
password: !secret wifi_ap_password
captive_portal:
web_server:
port: 80
#auth:
# username: !secret web_server_username
# password: !secret web_server_password
time:
- platform: homeassistant
id: homeassistant_time
text_sensor:
- platform: version
name: Version
- platform: wifi_info
ip_address:
name: IP Address
globals:
# Pins definieren
# # https://home.miot-spec.com/spec?type=urn:miot-spec-v2:device:kettle:0000A009:xiaomi-v21:1
# ################################################################
# # Service 2 - Main Kettle Functions
# ################################################################
# # Status sensor (SIID: 2, PIID: 1)
# # Permissions: Read notification
# # Values: 0=Idle, 1=Heating, 2=Boiling, 3=Cooling, 4=Keep Warm
# - id: kettle_status
# type: int
# restore_value: yes
# initial_value: '0'
# # Fault sensor (SIID: 2, PIID: 2)
# # Permissions: Read notification
# # Range: 0-255, Step: 1
# - id: kettle_fault
# type: int
# restore_value: yes
# initial_value: '0'
# Temperature sensor (SIID: 2, PIID: 3)
# Permissions: Read notification
# Range: -30°C to 100°C, Step: 1
- id: kettle_temperature
type: int
restore_value: yes
initial_value: '0'
# on_value:
# then:
# - if:
# condition:
# or:
# - lambda: "return id(kettle_temperature) > 100;"
# - lambda: "return id(kettle_temperature) >= id(kettle_target_temperature);"
# then:
# - switch.turn_off: heater_switch_relay
# - switch.turn_off: heater_switch_triac
# - logger.log:
# format: "Heater turned off - Temperature: %.1f°C, Target: %d°C"
# args: ["id(kettle_temperature)", "id(kettle_target_temperature)"]
# Target temperature (SIID: 2, PIID: 4)
# Permissions: Read and write, notifications
# Range: 40°C to 99°C, Step: 1
- id: kettle_target_temperature
type: int
restore_value: yes
initial_value: '40'
# # Auto keep warm (SIID: 2, PIID: 5)
# # Permissions: Read and write, notifications
# - id: kettle_auto_keep_warm
# type: bool
# restore_value: yes
# initial_value: 'false'
# # Keep warm temperature (SIID: 2, PIID: 6)
# # Permissions: Read and write, notifications
# # Range: 0°C to 100°C, Step: 1
# - id: kettle_keep_warm_temperature
# type: int
# restore_value: yes
# initial_value: '40'
# # Switch Status (SIID: 2, PIID: 7)
# # Permissions: Read and write, notifications
# - id: kettle_on
# type: bool
# restore_value: yes
# initial_value: 'false'
# ################################################################
# # Service 3 - Extended Functions
# ################################################################
# # Keep warm time (SIID: 3, PIID: 1)
# # Permissions: Read and write, notifications
# # Range: 60-1440, Step: 30
# - id: keep_warm_time
# type: int
# restore_value: yes
# initial_value: '60'
# # Custom knob temperature (SIID: 3, PIID: 2)
# # Permissions: Read and write, notifications
# - id: custom_knob_temp
# type: bool
# restore_value: yes
# initial_value: 'false'
# # Lift remember temperature (SIID: 3, PIID: 4)
# # Permissions: Read and write, notifications
# - id: lift_remember_temp
# type: bool
# restore_value: yes
# initial_value: 'false'
# # Boiling reminder (SIID: 3, PIID: 5)
# # Permissions: Read and write, notifications
# - id: boiling_reminder
# type: bool
# restore_value: yes
# initial_value: 'false'
# # Keep warm reminder (SIID: 3, PIID: 6)
# # Permissions: Read and write, notifications
# - id: keep_warm_reminder
# type: bool
# restore_value: yes
# initial_value: 'false'
# # Kettle lifting (SIID: 3, PIID: 7)
# # Permissions: Read notification
# - id: kettle_lifting
# type: bool
# restore_value: yes
# initial_value: 'false'
# # Extended mode (SIID: 3, PIID: 8)
# # Permissions: Read and write, notifications
# - id: extended_mode
# type: string
# restore_value: yes
# initial_value: '""'
# # Warming time (SIID: 3, PIID: 10)
# # Permissions: Read notification
# # Range: 0-720, Step: 1
# - id: warming_time
# type: int
# restore_value: yes
# initial_value: '0'
# # Target mode (SIID: 3, PIID: 11)
# # Permissions: Read and write, notifications
# # Range: 0-128, Step: 1
# - id: target_mode
# type: int
# restore_value: yes
# initial_value: '0'
# # Heat/Boil modes (SIID: 3, PIID: 12/13)
# # Permissions: Read and write, notifications
# - id: heat_mode
# type: string
# restore_value: yes
# initial_value: '""'
# - id: boil_mode
# type: string
# restore_value: yes
# initial_value: '""'
# ################################################################
# # Service 4 - Knob Settings
# ################################################################
# # Knob sequence (SIID: 4, PIID: 1)
# # Permissions: Read notification
# - id: knob_sequence
# type: string
# restore_value: yes
# initial_value: '""'
# # Knob positions (SIID: 4, PIID: 2-7)
# # Permissions: Read and write, notifications
# - id: knob_one
# type: string
# restore_value: yes
# initial_value: '""'
# - id: knob_two
# type: string
# restore_value: yes
# initial_value: '""'
# - id: knob_three
# type: string
# restore_value: yes
# initial_value: '""'
# - id: knob_four
# type: string
# restore_value: yes
# initial_value: '""'
# - id: knob_five
# type: string
# restore_value: yes
# initial_value: '""'
# - id: knob_six
# type: string
# restore_value: yes
# initial_value: '""'
# ################################################################
# # Service 5 - Local Timing
# ################################################################
# # Scene sequence (SIID: 5, PIID: 1)
# # Permissions: Read notification
# - id: scene_sequence
# type: string
# restore_value: yes
# initial_value: '""'
# # Scene settings (SIID: 5, PIID: 2-6)
# # Permissions: Read and write, notifications
# - id: scene_one
# type: string
# restore_value: yes
# initial_value: '""'
# - id: scene_two
# type: string
# restore_value: yes
# initial_value: '""'
# - id: scene_three
# type: string
# restore_value: yes
# initial_value: '""'
# - id: scene_four
# type: string
# restore_value: yes
# initial_value: '""'
# - id: scene_five
# type: string
# restore_value: yes
# initial_value: '""'
# ################################################################
# # Service 6 - Do Not Disturb
# ################################################################
# # Do not disturb (SIID: 6, PIID: 1)
# # Permissions: Read and write, notifications
# - id: do_not_disturb
# type: bool
# restore_value: yes
# initial_value: 'false'
binary_sensor:
- platform: status
name: Device Status
id: device_status
- platform: gpio
pin: GPIO18
name: "Button Boil - Touch"
id: button_boil_touch
- platform: gpio
pin: GPIO19
name: "Button Keep Warm - Touch"
id: button_keepwarm_touch
- platform: gpio
pin: GPIO39
name: "Unknown 39"
- platform: gpio
pin: GPIO34
name: "Unknown 34"
- platform: gpio
pin: GPIO35
name: "Unknown 35"
- platform: gpio
pin: GPIO32
name: "Unknown 32"
- platform: gpio
pin: GPIO25
name: "Unknown 25"
- platform: gpio
pin: GPIO14
name: "Unknown 14"
# - platform: gpio
# pin: GPIO33
# name: "Unknown 33"
sensor:
- platform: uptime # Uptime for this device
name: Uptime
update_interval: 60s
- platform: wifi_signal # Wifi Strength
name: Wifi Signal
update_interval: 60s
- platform: template
name: "Rotary Value"
id: rotary_value_sensor
unit_of_measurement: "°C"
accuracy_decimals: 0
update_interval: 60s
lambda: |-
return id(kettle_target_temperature);
- platform: rotary_encoder
id: rotation
pin_a: GPIO16
pin_b: GPIO17
resolution: 1
on_value:
then:
- lambda: |-
float step = 1;
if (abs(x) > 2) step = 2;
if (abs(x) > 4) step = 5;
float new_value = id(kettle_target_temperature) + (x * step);
new_value = std::min(99, std::max(40, static_cast<int>(new_value)));
id(kettle_target_temperature) = new_value;
id(rotary_value_sensor).publish_state(new_value);
- sensor.rotary_encoder.set_value:
id: rotation
value: 0
- platform: ntc
sensor: resistance_sensor_temperature
calibration:
b_constant: 3950
reference_temperature: 25°C
reference_resistance: 10kOhm
name: "NTC Temperature"
- platform: resistance
id: resistance_sensor_temperature
sensor: adc_sensor_temperature
configuration: UPSTREAM
reference_voltage: 3.3V
resistor: 10kOhm
name: "NTC Resistance Sensor"
- platform: adc
id: adc_sensor_temperature
pin: GPIO36
attenuation: 11db
update_interval: 1s
samples: 64
# Beispiel: ADC-Sensor zum Einlesen des Spannungspegels
- platform: adc
id: neutralspannung
pin: GPIO33 # Hier wird der analoge Eingang genutzt
name: "Neutralleiter Spannung"
update_interval: 2s
attenuation: 11db # Für höhere Eingangsspannungen (bis ca. 3.9V)
filters:
- median:
window_size: 7
send_every: 4
- sliding_window_moving_average:
window_size: 15
send_every: 15
- multiply: 3.3 # Falls notwendig, um den Messwert in Volt umzurechnen
unit_of_measurement: "V"
icon: "mdi:flash-outline"
output:
- platform: ledc
pin: GPIO4
id: buzzer_output
number:
- platform: template
name: "Buzzer Control"
id: buzzer_slider
min_value: 0
max_value: 100
step: 1
unit_of_measurement: "%"
optimistic: true
set_action:
then:
- if:
condition:
lambda: 'return x > 0;'
then:
- output.turn_on: buzzer_output
- output.ledc.set_frequency:
id: buzzer_output
frequency: 1000Hz
- output.set_level:
id: buzzer_output
level: !lambda "return x / 100.0;"
else:
- output.turn_off: buzzer_output
switch:
- platform: gpio
name: "Button Boil - Light"
pin: GPIO5
id: button_boil_light
inverted: true
- platform: gpio
name: "Button Keep Warm - Light"
pin: GPIO21
id: button_keepwarm_light
inverted: true
- platform: gpio
name: "Heater Main-Switch (Relay)"
pin: GPIO22
id: heater_switch_relay
- platform: gpio
name: "Heater Secondary-Switch (Triac)"
pin: GPIO23
id: heater_switch_triac
- platform: gpio
name: "Unknown Switch 12"
pin: GPIO12
id: switch_12
#https://github.com/ssieb/esphome_components/tree/master/components/ht16k33_alpha
display:
platform: tm1637
id: tm1637_display
clk_pin: GPIO26
dio_pin: GPIO27
length: 4 # Anzeige von 4 Zeichen
update_interval: 1s # Update-Intervall auf 1 Sekunde setzen
intensity: 4 # Helligkeit des Displays
lambda: |-
char buf[5];
sprintf(buf, "%02d", id(kettle_target_temperature));
it.print(buf);
Status:
2x touch button:
The two touch buttons are controlled via an SC02A sensor IC temperature-touch-magnet-sensors. This chip is connected to the ESP32 via GPIO18 and GPIO19. The status can be determined using HIGH or LOW.
Status: OK
2x status LED:
Two LEDs are built into the touch button, these can be switched via GPIO21 and GPIO5.
Status: OK
1x buzzer
The buzzer can be controlled via GPIO4.
Status: 80% (signal pattern still needs to be defined in the config)
1x Rotary Encoder Sensor
The rotary encoder sensor can be used to set the temperature. It is controlled via GPIO16 and GPIO17.
Status: OK
1x Heater Relay
The large relay K1 can be controlled via GPIO22 to control the heating element of the kettle.
Status: OK
1x Heater Triac
The triac Q1 can be controlled via GPIO23 to control the heating element of the kettle. The triac can be switched independently of the relay.
So far I have only tried on/off, but it may be possible to control it continuously (with the KO3211 Chip). The triac is probably used for noiseless switching of the kettle, for the keep-warm function.
Status: 50%
TX, RX, GPIO0:
A new firmware can be initially installed via TX,RX. GPIO0 puts the ESP32 into flash mode.
Thermometer:
The thermometer can be addressed via GPIO36 using NTC. NTC Sensor — ESPHome
The temperature can be measured precisely.
When the cooking pot is removed, the resistance changes considerably, allowing the status of the cooking pot to be recognized.
Status: 90%
Thermometer self-test:
I currently assume that a thermomenter self-test can be carried out via GPIO12. When transistor Q5 is activated, the resistance and thus the temperature changes by approx. 70 °C, but only when the cooking pot is plugged in.
This means that the thermometer can be tested and the status of the cooking pot can be detected 100%.
However, ESPHome config is required to use the functions
Status: 40%
Neutral conductor detection:
GPIO33 controls transistor Q4. I currently assume that this is a safety function that somehow monitors the neutral conductor.
Status: 20%
Display:
The display is addressed via GPIO27 (Clock) and GPIO26 (Data).
The display has the following functions:
- 2x 7-segment display to show numbers from 01 to 99.
- 1x Wifi symbol
- 1x °C symbol
- Red and blue LED.
At the moment I have not yet succeeded in controlling the display, with the TM1637 driver at least everything lights up and it flashes at refresh intervals.
Status: 10%