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

32
data/index.html Normal file
View File

@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Thermostat Config</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body { font-family: Arial, sans-serif; margin: 2em; }
label { display: block; margin-top: 1em; }
input, select { width: 100%; padding: 0.5em; }
button { margin-top: 2em; padding: 1em; width: 100%; }
</style>
</head>
<body>
<h2>Thermostat WiFi & MQTT Config</h2>
<form method="POST" action="/save">
<label>WiFi SSID<input name="ssid" required></label>
<label>WiFi Password<input name="wpass" type="password"></label>
<label>MQTT Server<input name="mqtt" required></label>
<label>MQTT Port<input name="mqttport" type="number" value="1883"></label>
<label>MQTT User<input name="mqttuser"></label>
<label>MQTT Password<input name="mqttpass" type="password"></label>
<label>Device ID<input name="devid" required></label>
<label>Temperature Sensor ID<input name="tempid" required></label>
<label>Confort Temp (°C)<input name="confort" type="number" value="20" step="0.1"></label>
<label>Eco Temp (°C)<input name="eco" type="number" value="17" step="0.1"></label>
<label>Boost Temp (°C)<input name="boost" type="number" value="22" step="0.1"></label>
<label>Hors Gel Temp (°C)<input name="horsgel" type="number" value="7" step="0.1"></label>
<button type="submit">Save & Reboot</button>
</form>
</body>
</html>

7
include/main.h Normal file
View File

@@ -0,0 +1,7 @@
//GPIO12 // Relay
//GPIO13 // LED
#define LED_PIN 13
#define RELAY_PIN 12

12
include/mqtt_handler.h Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include <Arduino.h>
#include <PubSubClient.h>
#include "thermostat.h"
extern float currentTemp; // Global temperature variable updated by MQTT callback
bool mqtt_connect(PubSubClient& client);
void mqtt_loop(PubSubClient& client);
void mqtt_publish_state(PubSubClient& client, ThermostatMode mode, float targetTemp, bool heating);
void mqtt_callback(char* topic, byte* payload, unsigned int length);

8
include/preset.h Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
#include <Arduino.h>
#include "thermostat.h"
void load_presets();
void save_presets();
float get_preset_temp(ThermostatMode mode);
void set_preset_temp(ThermostatMode mode, float temp);

21
include/thermostat.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
#include <Arduino.h>
enum ThermostatMode { MODE_OFF, MODE_CONFORT, MODE_ECO, MODE_BOOST, MODE_HORS_GEL };
class Thermostat {
public:
Thermostat();
void setMode(ThermostatMode mode);
void setTemperature(float temp);
void setPresetTemp(ThermostatMode mode, float temp);
void update(float currentTemp);
bool isHeating() const;
ThermostatMode getMode() const;
float getTargetTemp() const;
private:
ThermostatMode mode;
float presetTemps[5];
float targetTemp;
bool heating;
};

32
include/web_config.h Normal file
View File

@@ -0,0 +1,32 @@
#pragma once
#include <Arduino.h>
void setup_web_config();
void handle_web_config();
bool should_save_config();
void save_config();
void load_config();
#define CFG_STRLEN 64
/**
* Config struct for EEPROM storage.
*/
struct ConfigData
{
char wifi_ssid[CFG_STRLEN]; // Wifi SSID
char wifi_pass[CFG_STRLEN]; // Wifi Password
char mqtt_server[CFG_STRLEN]; // MQTT Server
char mqtt_user[CFG_STRLEN]; // MQTT User
char mqtt_pass[CFG_STRLEN]; // MQTT Password
char temp_sensor_id[CFG_STRLEN]; // Temperature Sensor ID
char mqtt_device_id[CFG_STRLEN]; // MQTT Device ID
char mqtt_temp_topic[CFG_STRLEN]; // MQTT Temperature Topic
int mqtt_port; // MQTT Port
float preset_confort; // Confort Mode Temperature
float preset_eco; // Eco Mode Temperature
float preset_boost; // Boost Mode Temperature
float preset_hors_gel; // Hors Gel Mode Temperature
};
extern ConfigData config;

2
include/web_routes.h Normal file
View File

@@ -0,0 +1,2 @@
#pragma once
void setup_web_routes();

View File

@@ -0,0 +1,4 @@
#include <ESPAsyncWebServer.h>
// Declare a global server instance on port 80
extern AsyncWebServer server;

367
monitor.log Normal file
View File

@@ -0,0 +1,367 @@
--- Terminal on /dev/ttyUSB0 | 115200 8-N-1
--- Available filters and text transformations: debug, default, direct, esp8266_exception_decoder, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C1388F5F89
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:8F:5F:89","mac_type":0,"adv_type":0,"rssi":-80,"servicedata":"895f8f38c1a462074d16e20a536b0e","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJW
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/43A69133165F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"43:A6:91:33:16:5F","mac_type":1,"adv_type":0,"rssi":-83,"servicedata":"0000000000000000000000000000000000000000","servicedatauuid":"0xfe9f"}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-66}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-82}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-88}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-86}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-82}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-66}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-82}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204010166e0036bf020bfe2036bf020be01580000000000","rssi":-66}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-87}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204010166e0036bf020bfe2036bf020be01580000000000","rssi":-74}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-81}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C13841E067
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:41:E0:67","mac_type":0,"adv_type":0,"rssi":-88,"servicedata":"a4c13841e067009542550b9bdd","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJWSD05
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C1388F5F89
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:8F:5F:89","mac_type":0,"adv_type":0,"rssi":-84,"servicedata":"895f8f38c1a465074d16e20a536c0e","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJW
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-91}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-81}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204010166e0036bf020bfe2036bf020be01580000000000","rssi":-74}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/43A69133165F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"43:A6:91:33:16:5F","mac_type":1,"adv_type":0,"rssi":-84,"servicedata":"0000000000000000000000000000000000000000","servicedatauuid":"0xfe9f"}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-66}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/43A69133165F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"43:A6:91:33:16:5F","mac_type":1,"adv_type":0,"rssi":-83,"servicedata":"0000000000000000000000000000000000000000","servicedatauuid":"0xfe9f"}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-90}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-81}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-87}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C1389ADA64
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:9A:DA:64","mac_type":0,"adv_type":0,"rssi":-63,"servicedata":"64da9a38c1a45907a316580a40e60e","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJW
-> OK! MQTT topic matches temp sensor ID. Processing message...
-> SUCCESS! Received tempc from MQTT: 18.81 °C
Current temperature (polled): 18.81
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C138CF2D7E
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:CF:2D:7E","mac_type":0,"adv_type":0,"rssi":-84,"servicedata":"7e2dcf38c1a43208d812970a49f60e","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJW
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C13841E067
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:41:E0:67","mac_type":0,"adv_type":0,"rssi":-89,"servicedata":"a4c13841e067009542550b9bdd","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJWSD05
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-82}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-66}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-73}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-82}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C13841E067
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:41:E0:67","mac_type":0,"adv_type":0,"rssi":-81,"servicedata":"a4c13841e067009542550b9bdd","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJWSD05
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-90}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C1388F5F89
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:8F:5F:89","mac_type":0,"adv_type":0,"rssi":-81,"servicedata":"895f8f38c1a461074e16e20a536e0e","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJW
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-66}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-84}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/43A69133165F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"43:A6:91:33:16:5F","mac_type":1,"adv_type":0,"rssi":-83,"servicedata":"0000000000000000000000000000000000000000","servicedatauuid":"0xfe9f"}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C138CF2D7E
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:CF:2D:7E","mac_type":0,"adv_type":0,"rssi":-78,"servicedata":"7e2dcf38c1a43208d812970a49f60e","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJW
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-88}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/43A69133165F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"43:A6:91:33:16:5F","mac_type":1,"adv_type":0,"rssi":-83,"servicedata":"0000000000000000000000000000000000000000","servicedatauuid":"0xfe9f"}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-82}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-98}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-74}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-84}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"name":"[TV] Samsung AU7095 65 TV","manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-72}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-86}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C13841E067
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:41:E0:67","mac_type":0,"adv_type":0,"name":"ATC_41E067","rssi":-88,"servicedata":"a4c13841e067009542550b9bdd","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id"
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C1389ADA64
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:9A:DA:64","mac_type":0,"adv_type":0,"rssi":-68,"servicedata":"64da9a38c1a45a079a16580a40e70e","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJW
-> OK! MQTT topic matches temp sensor ID. Processing message...
-> SUCCESS! Received tempc from MQTT: 18.82 °C
Current temperature (polled): 18.82
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-67}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-81}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-94}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-72}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-82}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-74}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-83}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C13841E067
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:41:E0:67","mac_type":0,"adv_type":0,"rssi":-86,"servicedata":"a4c13841e067009542550b9bdd","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJWSD05
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-96}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-93}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204010166e0036bf020bfe2036bf020be01580000000000","rssi":-72}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C1388F5F89
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:8F:5F:89","mac_type":0,"adv_type":0,"rssi":-80,"servicedata":"895f8f38c1a466074e16e30a53700e","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJW
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/43A69133165F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"43:A6:91:33:16:5F","mac_type":1,"adv_type":0,"rssi":-84,"servicedata":"0000000000000000000000000000000000000000","servicedatauuid":"0xfe9f"}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-83}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-82}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-67}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-94}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C1389ADA64
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:9A:DA:64","mac_type":0,"adv_type":0,"rssi":-69,"servicedata":"64da9a38c1a45b078f16590a40e90e","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJW
-> OK! MQTT topic matches temp sensor ID. Processing message...
-> SUCCESS! Received tempc from MQTT: 18.83 °C
Current temperature (polled): 18.83
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-86}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204012066210f0002014101010001000000000000000006","rssi":-74}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-82}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C13841E067
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:41:E0:67","mac_type":0,"adv_type":0,"rssi":-84,"servicedata":"a4c13841e067009542550b9bdd","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJWSD05
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/43A69133165F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"43:A6:91:33:16:5F","mac_type":1,"adv_type":0,"rssi":-83,"servicedata":"0000000000000000000000000000000000000000","servicedatauuid":"0xfe9f"}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204010166e0036bf020bfe2036bf020be01580000000000","rssi":-67}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-87}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/43A69133165F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"43:A6:91:33:16:5F","mac_type":1,"adv_type":0,"rssi":-83,"servicedata":"0000000000000000000000000000000000000000","servicedatauuid":"0xfe9f"}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-81}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C13841E067
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:41:E0:67","mac_type":0,"adv_type":0,"rssi":-87,"servicedata":"a4c13841e067009542550b9bdd","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJWSD05
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-94}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/43A69133165F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"43:A6:91:33:16:5F","mac_type":1,"adv_type":0,"rssi":-83,"servicedata":"0000000000000000000000000000000000000000","servicedatauuid":"0xfe9f"}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-81}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204010166e0036bf020bfe2036bf020be01580000000000","rssi":-74}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C138CF2D7E
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:CF:2D:7E","mac_type":0,"adv_type":0,"rssi":-84,"servicedata":"7e2dcf38c1a42e08d712970a49f90e","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJW
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C1388F5F89
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:8F:5F:89","mac_type":0,"adv_type":0,"rssi":-80,"servicedata":"895f8f38c1a462074d16e30a53710e","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJW
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204010166e0036bf020bfe2036bf020be01580000000000","rssi":-67}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/66FC2A8FC38F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"66:FC:2A:8F:C3:8F","mac_type":1,"adv_type":0,"rssi":-87}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/A4C13841E067
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"A4:C1:38:41:E0:67","mac_type":0,"adv_type":0,"rssi":-85,"servicedata":"a4c13841e067009642550b9bde","servicedatauuid":"0x181a","brand":"Xiaomi","model":"TH Sensor","model_id":"LYWSD03MMC/MJWSD05
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-84}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/43A69133165F
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"43:A6:91:33:16:5F","mac_type":1,"adv_type":0,"rssi":-83,"servicedata":"0000000000000000000000000000000000000000","servicedatauuid":"0xfe9f"}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/E0036BF020BF
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"E0:03:6B:F0:20:BF","mac_type":0,"adv_type":0,"manufacturerdata":"75004204010166e0036bf020bfe2036bf020be01580000000000","rssi":-74}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.
Topic: home/OMG_ESP32_BLE/BTtoMQTT/6FF06B19BD96
Searching for: 'A4C1389ADA64' in topic
Payload: {"id":"6F:F0:6B:19:BD:96","mac_type":1,"adv_type":0,"rssi":-84}
-> MQTT topic does not match expected temp sensor ID. Ignoring message.

16
platformio.ini Normal file
View File

@@ -0,0 +1,16 @@
[env:sonoff_basic]
platform = espressif8266
board = sonoff_basic
framework = arduino
monitor_speed = 115200
; upload_protocol = espota
; upload_port = 192.168.1.95
upload_speed = 115200
build_flags =
-DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
-DMQTT_MAX_PACKET_SIZE=512
lib_deps =
knolleary/PubSubClient
tzapu/WiFiManager
bblanchon/ArduinoJson
me-no-dev/ESPAsyncWebServer

151
src/main.cpp Normal file
View File

@@ -0,0 +1,151 @@
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Ticker.h>
#include <ArduinoOTA.h>
#include "thermostat.h"
#include "mqtt_handler.h"
#include "web_config.h"
#include "preset.h"
#include "web_routes.h"
#include "main.h"
#include "web_server_instance.h"
WiFiClient espClient;
PubSubClient mqttClient(espClient);
Thermostat thermostat;
Ticker ledTicker;
float currentTemp = 0.0;
float oldTemp = 0.0;
#define LED_PIN 13 // Sonoff Basic LED pin
// Toggle LED state
void toggleLED() {
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
/**
* Initialize serial, load configuration and presets, connect to WiFi and MQTT, and set up the thermostat.
*
*/
void setup() {
int i;
// Turn on LED to indicate startup (will turn off when setup is complete)
pinMode(LED_PIN, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
// Start with LED ON to indicate startup
digitalWrite(LED_PIN, LOW);
digitalWrite(RELAY_PIN, HIGH); // Ensure relay is off at startup
ledTicker.attach(0.2, toggleLED);
Serial.begin(115200);
i=0;
// Retrieve config from EEPROM, connect to WiFi and MQTT, and set up thermostat presets
load_config();
// Debug: print current config and actions
Serial.println("Thermostat Unit Startup - Version 1.0");
// Serial.print("WiFi SSID: "); Serial.println(config.wifi_ssid);
// Serial.print("MQTT Server: "); Serial.println(config.mqtt_server);
// Serial.print("MQTT Port: "); Serial.println(config.mqtt_port);
// Serial.print("MQTT User: "); Serial.println(config.mqtt_user);
// Serial.print("MQTT Device ID: "); Serial.println(config.mqtt_device_id);
// Serial.print("MQTT Temp Topic: "); Serial.println(config.mqtt_temp_topic);
// Serial.print("Temp Sensor ID: "); Serial.println(config.temp_sensor_id);
// Serial.print("Preset Confort: "); Serial.println(config.preset_confort);
// Serial.print("Preset Eco: "); Serial.println(config.preset_eco);
// Serial.print("Preset Boost: "); Serial.println(config.preset_boost);
// Serial.print("Preset Hors Gel: "); Serial.println(config.preset_hors_gel);
Serial.println("Connecting to WiFi...");
// setup wifi and mqtt, and load presets into thermostat
WiFi.begin(config.wifi_ssid, config.wifi_pass);
// Display wifi config
i=0;
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
i++;
if (i > 30) { // After 30 seconds of trying to connect, start config portal
Serial.println("\nFailed to connect to WiFi. Starting config portal...");
ledTicker.attach(0.5, toggleLED);
setup_web_config();
break;
}
delay(1000);
}
Serial.println("\nConnected to WiFi!");
ledTicker.detach();
digitalWrite(LED_PIN, LOW);
// Display IP
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
setup_web_routes();
server.begin();
Serial.println("Connecting to MQTT...");
mqttClient.setServer(config.mqtt_server, config.mqtt_port);
mqttClient.setCallback(mqtt_callback);
// Display MQTT buffer size
Serial.print("MQTT buffer size: ");
Serial.print(mqttClient.getBufferSize());
Serial.println(" bytes");
Serial.print("MQTT Client configured. Attempting to connect...");
mqttClient.connect(config.mqtt_device_id, config.mqtt_user, config.mqtt_pass);
if (mqttClient.connected()) {
Serial.println("MQTT Connected!");
// Subscribe with wildcard to get all sensors
String topic = String(config.mqtt_temp_topic) + "/#";
Serial.print("Subscribing to topic: ");
Serial.println(topic);
bool subResult = mqttClient.subscribe(topic.c_str());
Serial.print("Subscription result: ");
Serial.println(subResult ? "SUCCESS" : "FAILED");
} else {
Serial.print("MQTT Connection FAILED, state: ");
Serial.println(mqttClient.state());
}
// Start LED blinking to indicate normal operation (blink every 2 seconds)
ledTicker.attach(2.0, toggleLED);
Serial.println("Setup complete. Entering main loop...");
delay(1000); // Short delay to ensure LED state is visible before turning off
digitalWrite(RELAY_PIN, HIGH); // Ensure relay is on
delay(1000); // Short delay to ensure relay state is stable before turning off LED
digitalWrite(RELAY_PIN, LOW);
// Publsh initial state to MQTT to inform Home Assistant of current thermostat status on startup
mqtt_publish_state(mqttClient, thermostat.getMode(), thermostat.getTargetTemp(), thermostat.isHeating());
}
int j = 0;
void loop()
{
// Handle OTA updates
ArduinoOTA.handle();
// Ask Mqtt to process incoming messages and maintain connection
mqtt_loop(mqttClient);
// Poll the current temperature (updated asynchronously by MQTT callback)
if (currentTemp != oldTemp) {
Serial.print("Temperature change detected: ");
Serial.println(currentTemp);
oldTemp = currentTemp;
}
// // Update thermostat state based on current temp and publish state to MQTT
// thermostat.update(currentTemp);
// // Publish state to MQTT every second (or on state change, if you want to optimize)
// mqtt_publish_state(mqttClient, thermostat.getMode(), thermostat.getTargetTemp(), thermostat.isHeating());
// // Delay to avoid flooding MQTT with messages. Adjust as needed for your use case (e.g., publish on state change
// // instead of every loop).
delay(10);
}

103
src/mqtt_handler.cpp Normal file
View File

@@ -0,0 +1,103 @@
#include "mqtt_handler.h"
#include "thermostat.h"
#include <ArduinoJson.h>
#include "web_config.h"
// Helper function to normalize MAC address (remove colons, convert to uppercase)
String normalizeMac(const char* mac) {
String normalized = "";
for (int i = 0; mac[i] != '\0'; i++) {
if (mac[i] != ':') {
normalized += (char)toupper(mac[i]);
}
}
return normalized;
}
// Variables now defined in web_config.cpp
// Process incoming MQTT messages asynchronously
// The callback (mqtt_callback) is invoked automatically when messages arrive
void mqtt_loop(PubSubClient& client) {
client.loop();
}
void mqtt_publish_state(PubSubClient& client, ThermostatMode mode, float targetTemp, bool heating) {
JsonDocument doc;
doc["mode"] = mode;
doc["target"] = targetTemp;
doc["heating"] = heating;
char buf[128];
size_t n = serializeJson(doc, buf);
String topic = String("home/thermostat/") + String(config.mqtt_device_id) + String("/state");
client.publish(topic.c_str(), buf, n);
}
void mqtt_callback(char* topic, byte* payload, unsigned int length)
{
static bool first_call = true;
static String normalized_sensor_id;
if (first_call) {
// Serial.print("Looking for sensor ID: ");
// Serial.println(config.temp_sensor_id);
// FIX: Normalize the sensor ID to match topic format
// Topics come as: home/OMG_ESP32_BLE/BTtoMQTT/A4C1389ADA64 (no colons, uppercase)
// Config may have: A4:C1:38:9A:DA:64 (with colons)
// Solution: Remove colons and convert to uppercase for comparison
normalized_sensor_id = normalizeMac(config.temp_sensor_id);
// TESTING: Uncomment to test with a sensor that's actually broadcasting
// normalized_sensor_id = "A4C1389ADA64"; // Your Xiaomi (NOT broadcasting)
// normalized_sensor_id = "E0036BF020BF"; // Test with active sensor
// normalized_sensor_id = "74CBD1F131B6"; // Test with active sensor
// Serial.print("Normalized sensor ID: ");
// Serial.println(normalized_sensor_id);
first_call = false;
}
// Serial.print("Topic: ");
// Serial.println(topic);
// Debug: Print what we're comparing
// Serial.print(" Searching for: '");
// Serial.print(normalized_sensor_id);
// Serial.println("' in topic");
// Print payload for debugging (first 200 chars)
// Serial.print(" Payload: ");
// for (unsigned int i = 0; i < length && i < 200; i++) {
// Serial.write(payload[i]);
// }
// Serial.println();
// Check if topic contains the normalized sensor ID
if(strstr(topic, normalized_sensor_id.c_str()) == nullptr) {
// Serial.println(" -> MQTT topic does not match expected temp sensor ID. Ignoring message.");
return;
}
// Parse JSON payload from subscribed topic
JsonDocument doc;
// Serial.println(" -> OK! MQTT topic matches temp sensor ID. Processing message...");
DeserializationError err = deserializeJson(doc, payload, length);
if (err) {
Serial.print(" -> MQTT JSON parse error: ");
Serial.println(err.c_str());
return;
}
// Check for temperature field
if (doc["tempc"].is<float>()) {
currentTemp = doc["tempc"].as<float>();
// Serial.print(" -> SUCCESS! Received tempc from MQTT: ");
// Serial.print(currentTemp);
// Serial.println(" °C");
} else {
Serial.println(" -> WARNING: No 'tempc' field found in JSON payload");
}
}

39
src/preset.cpp Normal file
View File

@@ -0,0 +1,39 @@
#include "preset.h"
#include <EEPROM.h>
static float presets[5] = {0, 20.0, 17.0, 22.0, 7.0};
#define PRESET_EEPROM_START 0
#define PRESET_COUNT 5
#define PRESET_EEPROM_SIZE (PRESET_COUNT * sizeof(float))
void load_presets() {
EEPROM.begin(PRESET_EEPROM_SIZE);
bool valid = true;
for (int i = 0; i < PRESET_COUNT; ++i) {
float value = 0;
EEPROM.get(PRESET_EEPROM_START + i * sizeof(float), value);
// Check for uninitialized EEPROM (NaN or out of range)
if (isnan(value) || value < 0 || value > 50) {
valid = false;
break;
}
presets[i] = value;
}
if (!valid) {
// If invalid, write defaults
save_presets();
}
}
void save_presets() {
for (int i = 0; i < PRESET_COUNT; ++i) {
EEPROM.put(PRESET_EEPROM_START + i * sizeof(float), presets[i]);
}
EEPROM.commit();
}
float get_preset_temp(ThermostatMode mode) {
return presets[mode];
}
void set_preset_temp(ThermostatMode mode, float temp) {
presets[mode] = temp;
save_presets();
}

50
src/thermostat.cpp Normal file
View File

@@ -0,0 +1,50 @@
#include "thermostat.h"
Thermostat::Thermostat() : mode(MODE_OFF), targetTemp(0), heating(false) {
presetTemps[MODE_CONFORT] = 20.0;
presetTemps[MODE_ECO] = 17.0;
presetTemps[MODE_BOOST] = 22.0;
presetTemps[MODE_HORS_GEL] = 7.0;
presetTemps[MODE_OFF] = 0.0;
}
/**
* Set the thermostat mode. This will automatically update the target temperature to the preset for that mode.
*/
void Thermostat::setMode(ThermostatMode m) {
mode = m;
targetTemp = presetTemps[mode];
}
/**
* Manually set the target temperature. This does not change the mode or presets, but will override the preset for the
* current mode until the mode is changed again.
*/
void Thermostat::setTemperature(float temp) {
targetTemp = temp;
}
/**
* Set the preset temperature for a specific mode. If the current mode is the one being updated, also update the
* target temperature.
*/
void Thermostat::setPresetTemp(ThermostatMode m, float temp) {
presetTemps[m] = temp;
if (mode == m) targetTemp = temp;
}
/**
* Update the heating state based on the current temperature and target temperature.
* this is real simple logic: if current temp is below target, turn on heating, otherwise turn it off. In a real system, you would want to add some hysteresis to prevent rapid on/off cycling.
*/
void Thermostat::update(float currentTemp) {
if (mode == MODE_OFF) {
heating = false;
} else {
heating = (currentTemp < targetTemp);
}
}
bool Thermostat::isHeating() const { return heating; }
ThermostatMode Thermostat::getMode() const { return mode; }
float Thermostat::getTargetTemp() const { return targetTemp; }

126
src/web_config.cpp Normal file
View File

@@ -0,0 +1,126 @@
#include "web_config.h"
#include <WiFiManager.h>
#include <EEPROM.h>
// String wifi_ssid, wifi_pass, mqtt_server, mqtt_user, mqtt_pass, temp_sensor_id;
// String mqtt_device_id = "thermo1";
// String mqtt_temp_topic = "home/room/temperature/thermo1";
// int mqtt_port = 1883;
// float preset_confort = 21.0, preset_eco = 18.0, preset_boost = 23.0, preset_hors_gel = 7.0;
bool shouldSaveConfigFlag = false;
#define CFG_EEPROM_START 100
#define CFG_EEPROM_SIZE 512
ConfigData config; // Global config variable to hold current config in memory.
// This is what is read/written to EEPROM, and used by the rest of the code.
/**
* Config saving. In a production system, consider adding error handling and validation (e.g., check string lengths,
* valid port range, etc.).
* NB: config is stored as a struct for simplicity,
*/
void save_config() {
// Save config to EEPROM
EEPROM.begin(CFG_EEPROM_START + sizeof(ConfigData));
EEPROM.put(CFG_EEPROM_START, config);
EEPROM.commit();
// Reboot device to apply new config (e.g., reconnect to WiFi with new credentials)
ESP.restart();
}
/**
* Config loading from EEPROM.
* NB: config is stored as a struct for simplicity.
*
*/
void load_config() {
EEPROM.begin(CFG_EEPROM_START + sizeof(ConfigData));
EEPROM.get(CFG_EEPROM_START, config);
}
/**
* Web config setup. This will block until WiFi is configured, which is fine for initial setup but may not be ideal
* for all use cases.
*
* If config parameters are defined in EEPROm, try to connect to WiFi. If connection fails, start config portal.
* If parameters are not defined, start config portal directly.
* On config save, set shouldSaveConfigFlag to true so that main loop can save the config to EEPROM.
* This is a bit of a hack, but it allows us to avoid blocking the main loop while waiting for user input.
*/
void setup_web_config() {
WiFiManager wm;
// WiFiManagerParameter: id, placeholder, default, length
WiFiManagerParameter custom_mqtt_server("mqtt_server", "MQTT Server", config.mqtt_server, CFG_STRLEN);
WiFiManagerParameter custom_mqtt_port("mqtt_port", "MQTT Port", String(config.mqtt_port).c_str(), 6);
WiFiManagerParameter custom_mqtt_user("mqtt_user", "MQTT User", config.mqtt_user, CFG_STRLEN);
WiFiManagerParameter custom_mqtt_pass("mqtt_pass", "MQTT Password", config.mqtt_pass, CFG_STRLEN);
WiFiManagerParameter custom_temp_sensor_id("temp_sensor_id", "Temp Sensor ID", config.temp_sensor_id, CFG_STRLEN);
WiFiManagerParameter custom_mqtt_device_id("mqtt_device_id", "MQTT Device ID", config.mqtt_device_id, CFG_STRLEN);
WiFiManagerParameter custom_mqtt_temp_topic("mqtt_temp_topic", "MQTT Temp Topic", config.mqtt_temp_topic, CFG_STRLEN);
WiFiManagerParameter custom_preset_confort("preset_confort", "Preset Confort", String(config.preset_confort).c_str(), 8);
WiFiManagerParameter custom_preset_eco("preset_eco", "Preset Eco", String(config.preset_eco).c_str(), 8);
WiFiManagerParameter custom_preset_boost("preset_boost", "Preset Boost", String(config.preset_boost).c_str(), 8);
WiFiManagerParameter custom_preset_hors_gel("preset_hors_gel", "Preset Hors Gel", String(config.preset_hors_gel).c_str(), 8);
wm.addParameter(&custom_mqtt_server);
wm.addParameter(&custom_mqtt_port);
wm.addParameter(&custom_mqtt_user);
wm.addParameter(&custom_mqtt_pass);
wm.addParameter(&custom_temp_sensor_id);
wm.addParameter(&custom_mqtt_device_id);
wm.addParameter(&custom_mqtt_temp_topic);
wm.addParameter(&custom_preset_confort);
wm.addParameter(&custom_preset_eco);
wm.addParameter(&custom_preset_boost);
wm.addParameter(&custom_preset_hors_gel);
wm.setSaveConfigCallback([]() {
shouldSaveConfigFlag = true;
});
if (!wm.autoConnect("ThermostatConfig")) {
// If failed to connect or configure, restart or handle error
ESP.restart();
}
// Always update WiFi credentials after connection
String ssid = WiFi.SSID();
String pass = WiFi.psk();
ssid.toCharArray(config.wifi_ssid, CFG_STRLEN);
pass.toCharArray(config.wifi_pass, CFG_STRLEN);
// If config was changed, update variables and save
if (shouldSaveConfigFlag) {
strncpy(config.mqtt_server, custom_mqtt_server.getValue(), CFG_STRLEN);
config.mqtt_server[CFG_STRLEN-1] = '\0';
config.mqtt_port = String(custom_mqtt_port.getValue()).toInt();
strncpy(config.mqtt_user, custom_mqtt_user.getValue(), CFG_STRLEN);
config.mqtt_user[CFG_STRLEN-1] = '\0';
strncpy(config.mqtt_pass, custom_mqtt_pass.getValue(), CFG_STRLEN);
config.mqtt_pass[CFG_STRLEN-1] = '\0';
strncpy(config.temp_sensor_id, custom_temp_sensor_id.getValue(), CFG_STRLEN);
config.temp_sensor_id[CFG_STRLEN-1] = '\0';
strncpy(config.mqtt_device_id, custom_mqtt_device_id.getValue(), CFG_STRLEN);
config.mqtt_device_id[CFG_STRLEN-1] = '\0';
strncpy(config.mqtt_temp_topic, custom_mqtt_temp_topic.getValue(), CFG_STRLEN);
config.mqtt_temp_topic[CFG_STRLEN-1] = '\0';
config.preset_confort = String(custom_preset_confort.getValue()).toFloat();
config.preset_eco = String(custom_preset_eco.getValue()).toFloat();
config.preset_boost = String(custom_preset_boost.getValue()).toFloat();
config.preset_hors_gel = String(custom_preset_hors_gel.getValue()).toFloat();
save_config();
shouldSaveConfigFlag = false;
}
}
void handle_web_config() {
// No-op: all web server logic moved to web_routes.cpp
}
bool should_save_config() { return shouldSaveConfigFlag; }

126
src/web_routes.cpp Normal file
View File

@@ -0,0 +1,126 @@
#include <ESPAsyncWebServer.h>
#include "web_server_instance.h"
#include "web_config.h"
#include <string.h>
const char* config_html_template = R"HTML(
<html>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<style>
body { font-family: Arial, sans-serif; background: #f7f7f7; margin: 0; padding: 0; }
.container { max-width: 400px; margin: 30px auto; background: #fff; border-radius: 8px; box-shadow: 0 2px 8px #ccc; padding: 20px; }
h2 { text-align: center; color: #333; }
form { display: flex; flex-direction: column; }
label { margin-top: 12px; color: #555; font-size: 1em; }
input[type='text'], input[type='password'], input[type='number'] {
padding: 8px; margin-top: 4px; border: 1px solid #ccc; border-radius: 4px; font-size: 1em;
}
input[type='submit'] {
margin-top: 18px; padding: 12px; background: #007bff; color: #fff; border: none; border-radius: 4px; font-size: 1.1em; cursor: pointer;
}
input[type='submit']:active { background: #0056b3; }
</style>
</head>
<body>
<div class='container'>
<h2>Thermostat Config</h2>
<form method='POST' action='/config'>
<label>WiFi SSID:</label><input name='wifi_ssid' type='text' value='%WIFI_SSID%'>
<label>WiFi Pass:</label><input name='wifi_pass' type='password' value='%WIFI_PASS%'>
<label>MQTT Server:</label><input name='mqtt_server' type='text' value='%MQTT_SERVER%'>
<label>MQTT User:</label><input name='mqtt_user' type='text' value='%MQTT_USER%'>
<label>MQTT Pass:</label><input name='mqtt_pass' type='password' value='%MQTT_PASS%'>
<label>Temp Sensor ID:</label><input name='temp_sensor_id' type='text' value='%TEMP_SENSOR_ID%'>
<label>MQTT Device ID:</label><input name='mqtt_device_id' type='text' value='%MQTT_DEVICE_ID%'>
<label>MQTT Temp Topic:</label><input name='mqtt_temp_topic' type='text' value='%MQTT_TEMP_TOPIC%'>
<label>MQTT Port:</label><input name='mqtt_port' type='number' value='%MQTT_PORT%'>
<label>Preset Confort:</label><input name='preset_confort' type='number' step='0.1' value='%PRESET_CONFORT%'>
<label>Preset Eco:</label><input name='preset_eco' type='number' step='0.1' value='%PRESET_ECO%'>
<label>Preset Boost:</label><input name='preset_boost' type='number' step='0.1' value='%PRESET_BOOST%'>
<label>Preset Hors Gel:</label><input name='preset_hors_gel' type='number' step='0.1' value='%PRESET_HORS_GEL%'>
<input type='submit' value='Save'>
</form>
</div>
</body>
</html>
)HTML";
String render_config_html() {
String html(config_html_template);
html.replace("%WIFI_SSID%", String(config.wifi_ssid));
html.replace("%WIFI_PASS%", String(config.wifi_pass));
html.replace("%MQTT_SERVER%", String(config.mqtt_server));
html.replace("%MQTT_USER%", String(config.mqtt_user));
html.replace("%MQTT_PASS%", String(config.mqtt_pass));
html.replace("%TEMP_SENSOR_ID%", String(config.temp_sensor_id));
html.replace("%MQTT_DEVICE_ID%", String(config.mqtt_device_id));
html.replace("%MQTT_TEMP_TOPIC%", String(config.mqtt_temp_topic));
html.replace("%MQTT_PORT%", String(config.mqtt_port));
html.replace("%PRESET_CONFORT%", String(config.preset_confort));
html.replace("%PRESET_ECO%", String(config.preset_eco));
html.replace("%PRESET_BOOST%", String(config.preset_boost));
html.replace("%PRESET_HORS_GEL%", String(config.preset_hors_gel));
return html;
}
void setup_web_routes() {
// Serve config form at / and /config
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/html", render_config_html());
});
server.on("/config", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/html", render_config_html());
});
server.on("/config", HTTP_POST, [](AsyncWebServerRequest *request){
if (request->hasParam("wifi_ssid", true)) {
strncpy(config.wifi_ssid, request->getParam("wifi_ssid", true)->value().c_str(), CFG_STRLEN);
config.wifi_ssid[CFG_STRLEN-1] = '\0';
}
if (request->hasParam("wifi_pass", true)) {
strncpy(config.wifi_pass, request->getParam("wifi_pass", true)->value().c_str(), CFG_STRLEN);
config.wifi_pass[CFG_STRLEN-1] = '\0';
}
if (request->hasParam("mqtt_server", true)) {
strncpy(config.mqtt_server, request->getParam("mqtt_server", true)->value().c_str(), CFG_STRLEN);
config.mqtt_server[CFG_STRLEN-1] = '\0';
}
if (request->hasParam("mqtt_user", true)) {
strncpy(config.mqtt_user, request->getParam("mqtt_user", true)->value().c_str(), CFG_STRLEN);
config.mqtt_user[CFG_STRLEN-1] = '\0';
}
if (request->hasParam("mqtt_pass", true)) {
strncpy(config.mqtt_pass, request->getParam("mqtt_pass", true)->value().c_str(), CFG_STRLEN);
config.mqtt_pass[CFG_STRLEN-1] = '\0';
}
if (request->hasParam("temp_sensor_id", true)) {
strncpy(config.temp_sensor_id, request->getParam("temp_sensor_id", true)->value().c_str(), CFG_STRLEN);
config.temp_sensor_id[CFG_STRLEN-1] = '\0';
}
if (request->hasParam("mqtt_device_id", true)) {
strncpy(config.mqtt_device_id, request->getParam("mqtt_device_id", true)->value().c_str(), CFG_STRLEN);
config.mqtt_device_id[CFG_STRLEN-1] = '\0';
}
if (request->hasParam("mqtt_temp_topic", true)) {
strncpy(config.mqtt_temp_topic, request->getParam("mqtt_temp_topic", true)->value().c_str(), CFG_STRLEN);
config.mqtt_temp_topic[CFG_STRLEN-1] = '\0';
}
if (request->hasParam("mqtt_port", true)) {
config.mqtt_port = request->getParam("mqtt_port", true)->value().toInt();
}
if (request->hasParam("preset_confort", true)) {
config.preset_confort = request->getParam("preset_confort", true)->value().toFloat();
}
if (request->hasParam("preset_eco", true)) {
config.preset_eco = request->getParam("preset_eco", true)->value().toFloat();
}
if (request->hasParam("preset_boost", true)) {
config.preset_boost = request->getParam("preset_boost", true)->value().toFloat();
}
if (request->hasParam("preset_hors_gel", true)) {
config.preset_hors_gel = request->getParam("preset_hors_gel", true)->value().toFloat();
}
save_config();
request->send(200, "text/html", "<html><body><h2>Config Saved!</h2><a href='/config'>Back</a></body></html>");
});
}

View File

@@ -0,0 +1,3 @@
#include <ESPAsyncWebServer.h>
AsyncWebServer server(80); // Global server instance