Version OK avec Mqtt

This commit is contained in:
2026-03-16 11:20:10 +01:00
commit aa06085f5b
18 changed files with 1395 additions and 0 deletions

296
README.md Normal file
View File

@@ -0,0 +1,296 @@
# 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