Be Smart, Go Local.

DIY: Thermostat using a Sonoff Switch and Xiaomi Temperature Sensor

Make you own thermostat using a Sonoff Basic Switch and a Xiaomi Temperature & Humidity Sensor in Home Assistant!

If you consider yourself a smart home enthusiast, than you probably have come across multiple HVAC integrations and implementations in Home Assistant. Generally, people buy  off-the-shelf solutions such as the Nest Learning Thermostat, Amazon Smart Thermostat, Ecobee SmartThermostat and integrate it with their smart home environment. This is one way to do it, but if you have a big house with many rooms that need temperature control, it will get costly very fast.

In this article, I will show you how to make your own cheap, yet reliable heating thermostat, using a Sonoff Basic and Xiaomi Temperature & Humidity Sensor.
All within Home Assistant. Let’s get started!


In my guide, I am using a Sonoff Basic R2 Switch and a Xiaomi Mijia Temperature & Humidity sensor model LYWSD02. This can be achieved using any switch or sensor.

For our DIY project, we will need a couple of devices and optionally a couple of skills:

  • Running Home Assistant
  • Sonoff Basic Switch
  • Xiaomi Temperature & Humidity Sensor
  • (Optional) Basic Soldering skills
  • (Optional) Custom Firmware Flashing skills

Preparing the Sonoff Basic

Sonoff Basic R2

(Optional) Flashing custom firmware

The Sonoff is a cloud-connected Chinese device, which means it is operating its own firmware with its own mobile app. To get rid of this dependency, we need to flash the Sonoff with a custom open-source firmware, such as Tasmota or ESPHome.

For the purpose of this guide, I will not go into details about how you can flash the Sonoff, but you can follow these excellent guides as a starting point:

If you choose to flash the Sonoff switch, you then need to integrate it to Home Assistant using their official integrations. For my DIY project, I used a pre-flashed Sonoff basic with Tasmota.

(Optional) Continue without flashing

If you choose not to flash the switch, you can use AlexxIT’s SonoffLAN custom integration, to be able to control the Sonoff via Home Assistant. Follow the guide HERE.

(Optional) Turning the Sonoff into a dry relay switch

To connect the Sonoff Basic to your heating device, we (most likely) need to turn it into a dry relay switch. This is because we use 110V/220V to power the switch from the wall and the Sonoff will relay the same current to its output terminals. Most HVAC devices only support a dry circuit breaker installed to its input thermostat terminals and loading it with 110V/220V will fry its electronics. This is because outside current here is not needed:

  • Circuit open: HVAC off
  • Circuit closed: HVAC on

In our DIY project, the Sonoff Basic will act as a circuit breaker, thus turning the heating device on/off.

Note: It is possible that you do not need to turn the Sonoff into a dry relay switch. Maybe your heating entity does not care if current is supplied to its thermostat connector. Always do your due diligence and check the user manual!

As an alternative, you can purchase a low voltage Sonoff switch, operating on 5v, and use that in your DIY thermostat. For example:

Sonoff Basic 5V 
Sonoff Basic R2

I had a spare Sonoff Basic R2 laying around, so I decided to use that. To turn it into a dry contact relay, we need to break it open, cut out its output circuit on the PCB and do some soldering:

Step 1: Dissasemble the Sonoff Basic
Step 2:
On the top side of the PCB, we cut the N wire with small pliers 

Step 3: On the bottom side we cut the PCB with a small hand saw, to make path for the wire to be connected to the pin of the relay
Step 4: Next, we sever the connection of the relay pin to the input terminal
Step 5: Next, we solder the wire to the pin of the relay
Step 6: Reassemble the Sonoff Basic

Note: Always disconnect the switch from ANY connection first. If you are not comfortable doing this yourself, I suggest you find a qualified electrician who can do it for you. 

Switch Integration with Home Assistant

For my particular use case, I used a flashed Sonoff Basic with Tasmota. I had them flashed in batch when I first go them to eliminate cloud dependency. Once our Sonoff is turned into a dry contact relay and Tasmota is flashed, we can integrate it in Home Assistant using the official Tasmota integration and an MQTT Broker.

For the purpose of the length of this tutorial, we are not going to go into detail of installing Tasmota or Mosquitto MQTT. We will assume you have already integrated your switch into Home Assistant. Here are guides if you haven’t:

  • For installing Tasmota, click HERE
  • For installing Mosquitto MQTT broker, click HERE

Preparing the Temperature Sensor

Picking a temperature sensor

For my particular scenario, I am going to be using a cheap Xiaomi Mijia Temperature & Humidity sensor, model LYWSD02. These are cheap, run on small button batteries which can last years and advertise their current state quite frequently via BLE (Bluetooth Low Energy). As a plus, they have a beautiful E-Ink display, that shows time, temperature & humidity and a little smiley face which indicates comfort level.

If you don’t already own a temperature sensor, I would recommend the following models:

Xiaomi Mijia Temperature & Humidity Sensor LYWSD02

Xiaomi GlearGrass Temperature & Humidity Sensor CGG1

Note: You can use ANY sensor that feeds temperature data into Home Assistant to create your custom thermostat.

Sensor Integration with Home Assistant

Now that we picked our temperature monitor, we need to capture its BLE packets and feed them to Home Assistant. This data will control our Sonoff Basic switch and in turn, control our heating appliance. We will examine two options to do this:

  • Using the Raspberry Pi4 Bluetooth chip as a BLE Tracker (Integration via Passive BLE Monitor)
  • Using an ESP32 as a BLE Tracker (Integration via ESPHome)

If you have a spare ESP32 board, you can use it to bring the temperature sensor into HA.
If you are running HA on a Raspberry Pi, you can use its Bluetooth chip to capture the BLE packets from the temperature and humidity sensor. 

Whatever you device, range and placement will be crucial to maintain stability, as Bluetooth has a very low range in a crowded environment (Wi-Fi, ZigBee etc.). If you have a very large house, you can use multiple ESP32s and place them accordingly. Your other option would be to use a Wi-Fi or a ZigBee temperature sensor.

Note: If you have a ZigBee coordinator connected to your RPI, it is best to add a USB extension cable to the dongle. The USB ports on the Raspberry are known for being to “noisy” and creating interference with Bluetooth or Wi-Fi.

Passive BLE Monitor: Capture data with built-in Bluetooth module

This Home Assistant custom component is an alternative for the standard built in mitemp_bt integration and the Bluetooth LE Tracker integration that are available in Home Assistant. BLE monitor supports much more sensors than the build in integration from a variety of manufacturers.

Unlike the original mitemp_bt integration, which is getting its data by polling the device with a default five-minute interval, this custom component is parsing the Bluetooth Low Energy packets payload that is constantly emitted by the sensor. This does not affect the battery of the devices as much as the built-in integration.

It also solves connection issues some people have with the standard integration (due to passivity and the ability to collect data from multiple bt-interfaces simultaneously). BLE monitor also has the possibility to track BLE devices based on its (static) MAC address or its UUID. It will listen to incoming BLE advertisements for the devices that you have chosen to track.

The easiest way to setup passive BLE monitor is through the Home Assistant Community Store. 

  • Open HACS and click + Explore and download Repositories
  • Search for Passive BLE Monitor and click Download this repository with HACS
  • Restart Home Assistant
  • Open configuration in the sidebar, click Devices & Services
  • Click + Add Integration in the bottom right corner
  • Search for Passive BLE Monitor and select it
  • In the configuration pop-up, select your Bluetooth interface/adapter (usually hci0)
  • Check box “Discover devices and sensors automatically”
  • Click submit

For setting advanced parameters, or using yaml mode click HERE

Note: Many Xiaomi ecosystem sensors do not broadcast BLE advertisements containing useful data until they have gone through the “pairing” process in the MiHome app. The encryption key is also (re)set when adding the sensor to the MiHome app, so do this first. Some sensors also support alternative ATC firmware, which doesn’t need to be paired to MiHome.

After this component is setup, the BLE monitor should auto-discover our LYWSD02 Temperature & Humidity sensor and feed data in Home Assistant. You can rename its entities in the Developer Tools menu in HA.

ESPHome Setup: Turn your ESP32 into a BLE Tracker

To use an ESP32 as a Bluetooth Low Energy Tracker, we need to upload the esp32_ble_tracker component to it. To initially setup your ESP32 with the ESPHome addon in Home Assistant, follow this guide. Assuming your ESP32 is already installed and configured in ESPHome, containing your Wi-Fi credentials etc. click edit and add the following code:

    active: False
  #Living Room
  - platform: xiaomi_lywsd02
    mac_address: "E7:2E:01:40:XX:XX"
      name: "Living Room Temperature"
      name: "Living Room Humidity"
      name: "Living Room Battery Level"      

Replace the mac_address with your own from the sensor, rename them accordingly, click Save, click Install. ESPHome will compile your new firmware and flash it to your ESP32. After the flashing is done, you can click Logs and see the BLE packets data pouring in!

Note: The scan_parameters configuration variable can be set to scan for packets in a precise window of time. This largely depends of how your BLE sensor advertises data. I would suggest leaving active: False, as this ensures constant scanning so you do not miss any BLE packets! See more HERE

Creating our custom thermostat

To create our custom climate entity, we will use the Generic Thermostat platform of Home Assistant. To do this, we need to add the following code in our configuration.yaml file:

  - platform: generic_thermostat
    name: Living Room
    heater: switch.thermoflux
    target_sensor: sensor.living_room_temperature
    min_temp: 15
    max_temp: 35
    ac_mode: false
    cold_tolerance: 1
    hot_tolerance: 0
      seconds: 5
    initial_hvac_mode: "off"
    away_temp: 16
    precision: 0.1

The generic_thermostat platform offers a plethora of configuration variables, but for our DIY project these are the ones we we will use. We define the Sonoff basic switch as heater, the Temperature sensor as target_sensor. The other variables we are using:

  • name string REQUIRED, default: Generic Thermostat
    Name of thermostat.
  • heater string REQUIRED
    entity_id for heater switch, must be a toggle device. Becomes air conditioning switch when ac_mode is set to true.
  • target_sensor string REQUIRED
    entity_id for a temperature sensor, target_sensor.state must be temperature.
  • min_temp float (optional, default: 7)
    Set minimum set point available.
  • max_temp float (optional, default: 35)
    Set maximum set point available.
  • ac_mode boolean (optional, default: false)
    Set the switch specified in the heateroption to be treated as a cooling device instead of a heating device.
  • min_cycle_duration time | integer (optional)
    Set a minimum amount of time that the switch specified in the heateroption must be in its current state prior to being switched either off or on.
  • cold_tolerance float (optional, default: 0.3)
    Set a minimum amount of difference between the temperature read by the sensor specified in the target_sensoroption and the target temperature that must change prior to being switched on. For example, if the target temperature is 25 and the tolerance is 0.5 the heater will start when the sensor equals or goes below 24.5.
  • hot_tolerance float (optional, default: 0.3)
    Set a minimum amount of difference between the temperature read by the sensor specified in the target_sensoroption and the target temperature that must change prior to being switched off. For example, if the target temperature is 25 and the tolerance is 0.5 the heater will stop when the sensor equals or goes above 25.5.
  • initial_hvac_mode string (optional)
    Set the initial HVAC mode. Valid values are off, heat or cool. Value has to be double quoted. If this parameter is not set, it is preferable to set a keep_alive This is helpful to align any discrepancies between generic_thermostatand heater state.
  • away_temp float (optional)
    Set the temperature used by preset_mode: away.
  • precision float (optional)
    The desired precision for this device. Can be used to match your actual thermostat’s precision. Supported values are 0.1, 0.5 and 1.0. This value is also used as the step size for setting the target temperature. Default: 0.1 for Celsius and 1.0 for Fahrenheit.

Connecting the thermostat

In my case, I am going to use the thermostat we just created to control a Thermoflux Interio 18kw Pellet Stove. The brains of this particular pellet burner is a microcomputer by Italian company Micronova SRL. In reality this does not matter, we just needed to know how to connect the sonoff basic to the stove. On the back panel, there is a convenient thermostat terminal which is where we wire the switch. I have already confirmed that we need a dry contact relay, hence why we butchered the Sonoff Switch.

Controlling the Thermostat with Home Assistant

The generic_thermostat platform we used, created a combined entity from the switch and sensor called climate.living_room. Now we can use this entity to turn the stove on/off, change temperature, set home/away modes and much more! We can create a basic thermostat card with Lovelace:

As the basic Thermostat Card of Home Assistant is very limited, I have decided to use a custom card: Simple Thermostat Card by nervetattoo for a more minimalistic view.
You can find it in HACS > Frontend.

Track usage with History Stats

We can use the History Stats integration to track the entity and gather data and statistics about our thermostat, and in my case, my pellet stove. This component tracks the state of an entity and presents cumulative data in HA. For example, it can track the “on” state of our sonoff switch entity in a defined period of time:

Total time ON today & Times turned ON today

#Add this to your configuration.yaml
#Total Time On Today
  - platform: history_stats
    name: Thermoflux Time On Today
    entity_id: switch.thermoflux
    state: "on"
    type: time
    start: "{{ now().replace(hour=0, minute=0, second=0) }}"
    end: "{{ now() }}"
    scan_interval: 300
#Times Turned On Today    
  - platform: history_stats
    name: Thermoflux Times Turned On Today
    entity_id: switch.thermoflux
    state: "on"
    type: count
    start: "{{ now().replace(hour=0, minute=0, second=0) }}"
    end: "{{ now() }}"
    scan_interval: 300    

Visualizing history data

Using the new template sensors we created, we can visualize the data in Lovelace. The temperature sensor feeds data about temperature, humidity and battery very frequently in HA. Of course, we are once again going to use a custom card, as the basic cards are very limited in terms of customization. This is the ApexCharts Card by dev RomRider.

History Stats ApexCharts Card Example:

type: custom:apexcharts-card
    height: 170px
  color_threshold: true
graph_span: 14d
  end: day
  last_updated: true
  show: true
  show_states: true
  colorize_states: true
  title: Thermoflux Times Turned on Today
  show: true
  color: red
  label: Now
  - min: 0
    max: ~12
    decimals: 0
      tickAmount: 5
  - entity: sensor.thermoflux_times_turned_on_today
    type: column
      header_color_threshold: true
      extremas: true
    name: Times Turned On Today
      func: max
      duration: 1d
      - value: 1
        color: dodgerblue
      - value: 4
        color: darkcyan
      - value: 6
        color: goldenrod
      - value: 8
        color: orangered
      - value: 10
        color: darkred
  - entity: sensor.thermoflux_time_on_today
      as_duration: hour
      in_chart: false

Temperature & Humidity ApexCharts Card example:

type: custom:apexcharts-card
    height: 170px
  color_threshold: true
graph_span: 24h
  last_updated: true
  loading: false
  standard_format: false
  show: true
  show_states: true
  colorize_states: true
  title: Living Room Temperature
  show: true
  color: red
  label: Now
  start: day
  - entity: sensor.living_room_temperature
    type: line
    extend_to_end: false
      func: last
      duration: 15m
    stroke_width: 7
      extremas: true
      header_color_threshold: true
      - value: 18
        color: steelblue
      - value: 21
        color: midnightblue
      - value: 22
        color: orange
      - value: 23
        color: orangered
      - value: 24.5
        color: red
  - entity: sensor.living_room_humidity
      in_chart: false


This guide for a DIY Thermostat using a Sonoff Basic and a Xiaomi Mijia Temperature & Humidity Sensor is a fun do-it-yourself project in Home Assistant. It appears overwhelming but in reality is very simple. If implemented properly, it replaces expensive off-the-shelf thermostat solutions such as the Ecobee or Google’s Nest at no loss of features.

Scalability is not an issue, because the components used are very cheap and additional rooms can be controlled for as little as $25 ($7 Sonoff, $18 Temperature & Humidity Sensor!). Considering it is easily integrated in Home Assistant, the options for control and automation are limitless. Schedules, additional modes (away, vacation, etc.), history tracking, google home integration are some of the things you can achieve with this simple DIY.

6 thoughts on “DIY: Thermostat using a Sonoff Switch and Xiaomi Temperature Sensor”

  1. Really nice guide thank you!

    Is it possible with this setup to monitor wheter the hot water tap is running? So not the heating, the hot water Boiler. Just a simple on/off would suffice so I can link it to my fan and shower lights…

Comments are closed.