297 lines
9.5 KiB
Markdown
297 lines
9.5 KiB
Markdown
# Thermostat Project for Sonoff Basic R2
|
|
|
|
This project implements a WiFi thermostat using a Sonoff Basic R2, designed for integration with Home Assistant via MQTT. It supports preset modes (confort, eco, off, boost), receives room temperature from an MQTT gateway, and provides a fallback WiFi configuration portal for setup.
|
|
|
|
## Features
|
|
- MQTT-based Home Assistant integration as a thermostat device (with preset modes)
|
|
- Receives room temperature from an external MQTT sensor (e.g., Xiaomi)
|
|
- Fallback WiFi configuration page for setting WiFi, MQTT server, preset temperatures, and device ID
|
|
- Configurable preset temperatures (confort, eco, boost, hors gel)
|
|
- Clean code structure for maintainability
|
|
|
|
## Project Structure
|
|
- `src/` : Main application logic
|
|
- `include/` : Header files
|
|
- `data/` : Static files for web configuration portal
|
|
- `platformio.ini` : PlatformIO project configuration
|
|
- `README.md` : This documentation
|
|
|
|
## Getting Started
|
|
|
|
### 1. Prerequisites
|
|
- PlatformIO extension for VS Code
|
|
- Sonoff Basic R2 device
|
|
- MQTT broker (e.g., Mosquitto)
|
|
- Home Assistant instance
|
|
|
|
### 2. Build & Upload
|
|
1. Clone this repository or copy the folder to your PlatformIO workspace.
|
|
2. Edit `platformio.ini` if needed (WiFi/MQTT credentials can be set via the web portal after first boot).
|
|
3. Build and upload the firmware to your Sonoff Basic R2.
|
|
|
|
### 3. First Boot & Configuration
|
|
- On first boot (or if WiFi/MQTT fails), the device starts a WiFi AP for configuration.
|
|
- Connect to the AP and open the captive portal to set:
|
|
- WiFi SSID/password
|
|
- MQTT server/port/credentials
|
|
- Preset temperatures (confort, eco, boost, hors gel)
|
|
- Device ID for temperature sensor
|
|
|
|
### 4. Home Assistant Integration
|
|
- The device publishes/receives via MQTT using the Home Assistant climate platform.
|
|
- Preset modes (confort, eco, off, boost) are supported and can be set from Home Assistant.
|
|
- The device subscribes to a temperature topic (e.g., from a Xiaomi sensor via Zigbee2MQTT).
|
|
|
|
## Home Assistant Integration
|
|
|
|
### MQTT Topics
|
|
|
|
The thermostat uses the following MQTT topics:
|
|
|
|
**Temperature Input (Subscribe):**
|
|
```
|
|
home/OMG_ESP32_BLE/BTtoMQTT/<SENSOR_MAC_ADDRESS>
|
|
```
|
|
- The device subscribes to receive temperature updates from your sensor
|
|
- Example: `home/OMG_ESP32_BLE/BTtoMQTT/A4C1389ADA64`
|
|
- Payload format: `{"tempc": 21.5, "hum": 45.2, "batt": 85, ...}`
|
|
- Only the `tempc` field is required
|
|
|
|
**Thermostat State (Publish):**
|
|
```
|
|
home/thermostat/<DEVICE_ID>/state
|
|
```
|
|
- The device publishes its current state
|
|
- Payload format: `{"mode": 1, "target": 21.0, "heating": true}`
|
|
|
|
**Thermostat Commands (Subscribe):**
|
|
```
|
|
home/thermostat/<DEVICE_ID>/set
|
|
```
|
|
- Home Assistant sends commands to control the thermostat
|
|
- Payload format: `{"mode": 1, "target": 22.0}`
|
|
|
|
### Manual Configuration in Home Assistant
|
|
|
|
Add the following to your Home Assistant `configuration.yaml`:
|
|
|
|
```yaml
|
|
mqtt:
|
|
climate:
|
|
- name: "Living Room Thermostat"
|
|
unique_id: "thermostat_living_room"
|
|
|
|
# Current temperature from sensor
|
|
current_temperature_topic: "home/OMG_ESP32_BLE/BTtoMQTT/A4C1389ADA64"
|
|
current_temperature_template: "{{ value_json.tempc }}"
|
|
|
|
# Temperature control
|
|
temperature_command_topic: "home/thermostat/sonoff_thermo_01/set"
|
|
temperature_state_topic: "home/thermostat/sonoff_thermo_01/state"
|
|
temperature_state_template: "{{ value_json.target }}"
|
|
|
|
# Mode control
|
|
mode_command_topic: "home/thermostat/sonoff_thermo_01/set"
|
|
mode_command_template: '{"mode": {% if value == "off" %}0{% elif value == "heat" %}1{% endif %}}'
|
|
mode_state_topic: "home/thermostat/sonoff_thermo_01/state"
|
|
mode_state_template: >
|
|
{% if value_json.mode == 0 %}off
|
|
{% elif value_json.mode == 1 %}heat
|
|
{% else %}off{% endif %}
|
|
modes:
|
|
- "off"
|
|
- "heat"
|
|
|
|
# Preset modes (confort, eco, boost, hors gel)
|
|
preset_mode_command_topic: "home/thermostat/sonoff_thermo_01/set"
|
|
preset_mode_command_template: >
|
|
{"mode": {% if value == "comfort" %}1
|
|
{% elif value == "eco" %}2
|
|
{% elif value == "boost" %}3
|
|
{% elif value == "away" %}4
|
|
{% else %}0{% endif %}}
|
|
preset_mode_state_topic: "home/thermostat/sonoff_thermo_01/state"
|
|
preset_mode_value_template: >
|
|
{% if value_json.mode == 1 %}comfort
|
|
{% elif value_json.mode == 2 %}eco
|
|
{% elif value_json.mode == 3 %}boost
|
|
{% elif value_json.mode == 4 %}away
|
|
{% else %}none{% endif %}
|
|
preset_modes:
|
|
- "comfort"
|
|
- "eco"
|
|
- "boost"
|
|
- "away"
|
|
|
|
# Temperature settings
|
|
min_temp: 5
|
|
max_temp: 30
|
|
temp_step: 0.5
|
|
precision: 0.1
|
|
|
|
sensor:
|
|
- platform: mqtt
|
|
name: "Living Room Temperature"
|
|
state_topic: "home/OMG_ESP32_BLE/BTtoMQTT/A4C1389ADA64"
|
|
value_template: "{{ value_json.tempc }}"
|
|
unit_of_measurement: "°C"
|
|
device_class: temperature
|
|
|
|
- platform: mqtt
|
|
name: "Living Room Humidity"
|
|
state_topic: "home/OMG_ESP32_BLE/BTtoMQTT/A4C1389ADA64"
|
|
value_template: "{{ value_json.hum }}"
|
|
unit_of_measurement: "%"
|
|
device_class: humidity
|
|
|
|
binary_sensor:
|
|
- platform: mqtt
|
|
name: "Living Room Thermostat Heating"
|
|
state_topic: "home/thermostat/sonoff_thermo_01/state"
|
|
value_template: "{{ value_json.heating }}"
|
|
payload_on: true
|
|
payload_off: false
|
|
device_class: heat
|
|
```
|
|
|
|
**Important:** Replace:
|
|
- `A4C1389ADA64` with your Xiaomi sensor's MAC address (without colons)
|
|
- `sonoff_thermo_01` with your device ID configured in the web portal
|
|
|
|
### Using the Thermostat in Home Assistant
|
|
|
|
After configuration and restart, you can:
|
|
|
|
1. **Set Temperature:** Use the climate card to adjust target temperature
|
|
2. **Change Modes:**
|
|
- **Off:** Heating disabled
|
|
- **Heat:** Heating enabled with current preset
|
|
3. **Select Presets:**
|
|
- **Comfort:** Standard comfort temperature (e.g., 21°C)
|
|
- **Eco:** Energy-saving mode (e.g., 19°C)
|
|
- **Boost:** Maximum heating (e.g., 24°C)
|
|
- **Away (Hors Gel):** Frost protection (e.g., 7°C)
|
|
|
|
### Automation Example
|
|
|
|
```yaml
|
|
automation:
|
|
- alias: "Thermostat Night Mode"
|
|
trigger:
|
|
- platform: time
|
|
at: "22:00:00"
|
|
action:
|
|
- service: climate.set_preset_mode
|
|
target:
|
|
entity_id: climate.living_room_thermostat
|
|
data:
|
|
preset_mode: "eco"
|
|
|
|
- alias: "Thermostat Morning Mode"
|
|
trigger:
|
|
- platform: time
|
|
at: "06:30:00"
|
|
condition:
|
|
- condition: state
|
|
entity_id: binary_sensor.workday
|
|
state: "on"
|
|
action:
|
|
- service: climate.set_preset_mode
|
|
target:
|
|
entity_id: climate.living_room_thermostat
|
|
data:
|
|
preset_mode: "comfort"
|
|
```
|
|
|
|
### Lovelace Card Example
|
|
|
|
```yaml
|
|
type: thermostat
|
|
entity: climate.living_room_thermostat
|
|
features:
|
|
- type: climate-preset-modes
|
|
preset_modes:
|
|
- comfort
|
|
- eco
|
|
- boost
|
|
- away
|
|
```
|
|
|
|
### Troubleshooting
|
|
|
|
**No temperature updates:**
|
|
1. Check MQTT broker logs: `mosquitto_sub -h localhost -t "home/OMG_ESP32_BLE/BTtoMQTT/#" -v`
|
|
2. Verify sensor MAC address matches configuration (use uppercase without colons)
|
|
3. Check sensor battery level
|
|
4. Ensure sensor is in range of BLE gateway
|
|
|
|
**Thermostat not responding to commands:**
|
|
1. Verify MQTT topics match your device ID
|
|
2. Check MQTT broker connection from Home Assistant
|
|
3. Monitor device serial output for errors
|
|
4. Ensure MQTT buffer size is set to 512 bytes (see `platformio.ini`)
|
|
|
|
**Important Note:** The default MQTT buffer size for PubSubClient is 128 bytes, which is too small for Xiaomi sensor payloads (~317 bytes). This project increases it to 512 bytes via the build flag `-DMQTT_MAX_PACKET_SIZE=512` in `platformio.ini`.
|
|
|
|
### 5. File Overview
|
|
- `src/main.cpp` : Main application entry point
|
|
- `src/thermostat.cpp` / `include/thermostat.h` : Thermostat logic
|
|
- `src/mqtt_handler.cpp` / `include/mqtt_handler.h` : MQTT communication
|
|
- `src/web_config.cpp` / `include/web_config.h` : WiFi/MQTT/web config portal
|
|
- `src/preset.cpp` / `include/preset.h` : Preset management
|
|
- `data/` : HTML/CSS/JS for configuration portal
|
|
|
|
## Example MQTT Topics
|
|
- Temperature: `home/room/temperature/<device_id>`
|
|
- State: `home/thermostat/<device_id>/state`
|
|
- Command: `home/thermostat/<device_id>/set`
|
|
|
|
## Over-The-Air (OTA) Updates
|
|
|
|
The thermostat supports OTA updates, allowing you to upload new firmware wirelessly without physical access to the device.
|
|
|
|
### Using OTA with PlatformIO
|
|
|
|
1. **Ensure the device is connected to WiFi** and note its IP address from the serial monitor
|
|
|
|
2. **Configure OTA upload in platformio.ini** (optional - for easier uploads):
|
|
```ini
|
|
upload_protocol = espota
|
|
upload_port = <DEVICE_IP_ADDRESS>
|
|
```
|
|
|
|
3. **Upload via OTA**:
|
|
```bash
|
|
# Using PlatformIO CLI
|
|
platformio run --target upload --upload-port <DEVICE_IP_ADDRESS>
|
|
|
|
# Or use the PlatformIO IDE upload button after setting upload_protocol
|
|
```
|
|
|
|
### Using OTA with Arduino IDE
|
|
|
|
1. Open **Tools > Port** and select the network port (shows as `<device_hostname> at <IP>`)
|
|
2. Click **Upload** as normal
|
|
|
|
### OTA Behavior
|
|
|
|
- During OTA update, the LED stays solid ON
|
|
- Progress is shown in the serial monitor
|
|
- Device automatically reboots after successful update
|
|
- If OTA fails, the device continues running the existing firmware
|
|
|
|
### Security Note
|
|
|
|
By default, OTA has no password protection. For production use, add a password:
|
|
```cpp
|
|
ArduinoOTA.setPassword("your-password-here");
|
|
```
|
|
|
|
## Advanced
|
|
- Fallback to AP mode if WiFi or MQTT fails
|
|
- All configuration is stored in flash and can be reset via the web portal
|
|
- OTA updates for remote firmware deployment
|
|
|
|
## License
|
|
MIT
|