esphome 2024.10.3__py3-none-any.whl → 2024.11.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +22 -4
- esphome/automation.py +29 -2
- esphome/components/animation/__init__.py +5 -8
- esphome/components/animation/animation.cpp +1 -1
- esphome/components/audio/__init__.py +9 -0
- esphome/components/audio/audio.h +21 -0
- esphome/components/axs15231/__init__.py +6 -0
- esphome/components/axs15231/touchscreen/__init__.py +36 -0
- esphome/components/axs15231/touchscreen/axs15231_touchscreen.cpp +64 -0
- esphome/components/axs15231/touchscreen/axs15231_touchscreen.h +27 -0
- esphome/components/bme68x_bsec2/__init__.py +1 -1
- esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +50 -47
- esphome/components/bme68x_bsec2/bme68x_bsec2.h +0 -2
- esphome/components/bytebuffer/__init__.py +5 -0
- esphome/components/bytebuffer/bytebuffer.h +421 -0
- esphome/components/climate/__init__.py +14 -13
- esphome/components/datetime/__init__.py +3 -3
- esphome/components/debug/debug_esp32.cpp +16 -8
- esphome/components/dfplayer/dfplayer.cpp +132 -6
- esphome/components/dfplayer/dfplayer.h +19 -53
- esphome/components/display/display.cpp +142 -0
- esphome/components/display/display.h +7 -0
- esphome/components/es8311/__init__.py +0 -0
- esphome/components/es8311/audio_dac.py +70 -0
- esphome/components/es8311/es8311.cpp +227 -0
- esphome/components/es8311/es8311.h +135 -0
- esphome/components/es8311/es8311_const.h +195 -0
- esphome/components/esp32/boards.py +199 -1
- esphome/components/esp32/gpio.py +3 -1
- esphome/components/esp32_ble/const_esp32c6.h +7 -0
- esphome/components/esp32_ble_client/ble_client_base.h +1 -1
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +3 -0
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +2 -1
- esphome/components/esp32_rmt_led_strip/led_strip.cpp +2 -2
- esphome/components/esp32_rmt_led_strip/led_strip.h +2 -0
- esphome/components/esp32_rmt_led_strip/light.py +3 -1
- esphome/components/esp8266/gpio.py +7 -5
- esphome/components/ethernet/__init__.py +55 -1
- esphome/components/ethernet/ethernet_component.cpp +14 -1
- esphome/components/ethernet/ethernet_component.h +7 -1
- esphome/components/font/__init__.py +213 -108
- esphome/components/gp8403/output/__init__.py +1 -1
- esphome/components/host/gpio.py +6 -4
- esphome/components/http_request/__init__.py +12 -0
- esphome/components/http_request/http_request.h +65 -3
- esphome/components/http_request/http_request_arduino.cpp +4 -3
- esphome/components/http_request/http_request_idf.cpp +12 -14
- esphome/components/http_request/ota/ota_http_request.cpp +1 -1
- esphome/components/http_request/update/http_request_update.cpp +1 -1
- esphome/components/i2c_device/__init__.py +26 -0
- esphome/components/i2c_device/i2c_device.cpp +17 -0
- esphome/components/i2c_device/i2c_device.h +18 -0
- esphome/components/i2s_audio/__init__.py +1 -3
- esphome/components/i2s_audio/speaker/__init__.py +12 -4
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +426 -200
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +92 -33
- esphome/components/ili9xxx/display.py +5 -1
- esphome/components/image/__init__.py +5 -8
- esphome/components/image/image.cpp +14 -14
- esphome/components/image/image.h +20 -24
- esphome/components/internal_temperature/internal_temperature.cpp +51 -2
- esphome/components/internal_temperature/internal_temperature.h +1 -0
- esphome/components/ld2420/ld2420.cpp +1 -1
- esphome/components/libretiny/gpio.py +4 -2
- esphome/components/light/__init__.py +32 -1
- esphome/components/light/automation.py +39 -32
- esphome/components/light/effects.py +36 -36
- esphome/components/light/light_state.cpp +6 -16
- esphome/components/light/light_state.h +34 -0
- esphome/components/light/types.py +3 -1
- esphome/components/logger/logger_esp32.cpp +15 -0
- esphome/components/lvgl/__init__.py +202 -95
- esphome/components/lvgl/automation.py +42 -40
- esphome/components/lvgl/binary_sensor/__init__.py +8 -15
- esphome/components/lvgl/defines.py +14 -8
- esphome/components/lvgl/encoders.py +11 -8
- esphome/components/lvgl/keypads.py +77 -0
- esphome/components/lvgl/light/__init__.py +6 -8
- esphome/components/lvgl/lv_validation.py +2 -4
- esphome/components/lvgl/lvcode.py +3 -9
- esphome/components/lvgl/lvgl_esphome.cpp +210 -89
- esphome/components/lvgl/lvgl_esphome.h +113 -30
- esphome/components/lvgl/lvgl_proxy.h +17 -0
- esphome/components/lvgl/number/__init__.py +10 -15
- esphome/components/lvgl/schemas.py +4 -2
- esphome/components/lvgl/select/__init__.py +12 -37
- esphome/components/lvgl/select/lvgl_select.h +27 -33
- esphome/components/lvgl/sensor/__init__.py +8 -14
- esphome/components/lvgl/styles.py +3 -4
- esphome/components/lvgl/switch/__init__.py +8 -13
- esphome/components/lvgl/text/__init__.py +5 -6
- esphome/components/lvgl/text_sensor/__init__.py +15 -15
- esphome/components/lvgl/touchscreens.py +2 -3
- esphome/components/lvgl/trigger.py +7 -9
- esphome/components/lvgl/types.py +9 -3
- esphome/components/lvgl/widgets/__init__.py +32 -21
- esphome/components/lvgl/widgets/dropdown.py +22 -10
- esphome/components/lvgl/widgets/msgbox.py +6 -5
- esphome/components/lvgl/widgets/obj.py +4 -2
- esphome/components/lvgl/widgets/page.py +3 -2
- esphome/components/lvgl/widgets/qrcode.py +54 -0
- esphome/components/lvgl/widgets/roller.py +21 -14
- esphome/components/lvgl/widgets/tileview.py +2 -1
- esphome/components/max17043/__init__.py +1 -0
- esphome/components/max17043/automation.h +20 -0
- esphome/components/max17043/max17043.cpp +98 -0
- esphome/components/max17043/max17043.h +29 -0
- esphome/components/max17043/sensor.py +77 -0
- esphome/components/media_player/__init__.py +11 -0
- esphome/components/media_player/automation.h +10 -0
- esphome/components/media_player/media_player.cpp +4 -0
- esphome/components/midea/air_conditioner.cpp +17 -1
- esphome/components/mlx90393/sensor.py +1 -1
- esphome/components/modbus_controller/__init__.py +31 -1
- esphome/components/modbus_controller/automation.h +16 -0
- esphome/components/modbus_controller/const.py +2 -0
- esphome/components/modbus_controller/modbus_controller.cpp +14 -2
- esphome/components/modbus_controller/modbus_controller.h +9 -0
- esphome/components/mopeka_pro_check/mopeka_pro_check.cpp +40 -21
- esphome/components/mopeka_pro_check/mopeka_pro_check.h +9 -2
- esphome/components/mopeka_pro_check/sensor.py +41 -0
- esphome/components/mqtt/__init__.py +36 -0
- esphome/components/mqtt/mqtt_client.cpp +27 -3
- esphome/components/mqtt/mqtt_client.h +27 -2
- esphome/components/mqtt/mqtt_climate.cpp +4 -2
- esphome/components/mqtt/mqtt_component.cpp +6 -0
- esphome/components/mqtt/mqtt_component.h +4 -0
- esphome/components/mqtt/mqtt_const.h +6 -0
- esphome/components/online_image/online_image.cpp +2 -8
- esphome/components/online_image/online_image.h +2 -6
- esphome/components/opentherm/__init__.py +35 -9
- esphome/components/opentherm/binary_sensor/__init__.py +33 -0
- esphome/components/opentherm/const.py +11 -0
- esphome/components/opentherm/generate.py +142 -0
- esphome/components/opentherm/hub.cpp +130 -24
- esphome/components/opentherm/hub.h +62 -9
- esphome/components/opentherm/input.h +18 -0
- esphome/components/opentherm/input.py +51 -0
- esphome/components/opentherm/number/__init__.py +74 -0
- esphome/components/opentherm/number/number.cpp +40 -0
- esphome/components/opentherm/number/number.h +31 -0
- esphome/components/opentherm/opentherm.cpp +30 -0
- esphome/components/opentherm/opentherm.h +34 -2
- esphome/components/opentherm/opentherm_macros.h +151 -0
- esphome/components/opentherm/output/__init__.py +47 -0
- esphome/components/opentherm/output/output.cpp +18 -0
- esphome/components/opentherm/output/output.h +33 -0
- esphome/components/opentherm/schema.py +814 -0
- esphome/components/opentherm/sensor/__init__.py +51 -0
- esphome/components/opentherm/switch/__init__.py +43 -0
- esphome/components/opentherm/switch/switch.cpp +28 -0
- esphome/components/opentherm/switch/switch.h +20 -0
- esphome/components/opentherm/validate.py +31 -0
- esphome/components/pcd8544/display.py +8 -4
- esphome/components/prometheus/prometheus_handler.cpp +176 -14
- esphome/components/prometheus/prometheus_handler.h +25 -7
- esphome/components/qspi_amoled/display.py +1 -141
- esphome/components/qspi_dbi/display.py +185 -0
- esphome/components/qspi_dbi/models.py +64 -0
- esphome/components/{qspi_amoled/qspi_amoled.cpp → qspi_dbi/qspi_dbi.cpp} +95 -46
- esphome/components/{qspi_amoled/qspi_amoled.h → qspi_dbi/qspi_dbi.h} +26 -15
- esphome/components/rp2040/__init__.py +6 -3
- esphome/components/rp2040/gpio.py +5 -3
- esphome/components/rtttl/rtttl.cpp +4 -1
- esphome/components/rtttl/rtttl.h +1 -0
- esphome/components/sdl/sdl_esphome.cpp +22 -5
- esphome/components/sdl/sdl_esphome.h +1 -0
- esphome/components/sdm_meter/sdm_meter.cpp +1 -1
- esphome/components/sensor/__init__.py +18 -8
- esphome/components/sensor/filter.cpp +19 -18
- esphome/components/sensor/filter.h +9 -10
- esphome/components/sgp4x/sgp4x.cpp +40 -74
- esphome/components/sgp4x/sgp4x.h +5 -3
- esphome/components/speaker/__init__.py +51 -5
- esphome/components/speaker/automation.h +25 -0
- esphome/components/speaker/speaker.h +72 -1
- esphome/components/spi/__init__.py +15 -14
- esphome/components/spi_device/__init__.py +4 -15
- esphome/components/ssd1306_spi/display.py +6 -2
- esphome/components/ssd1322_spi/display.py +6 -2
- esphome/components/ssd1325_spi/display.py +6 -2
- esphome/components/ssd1327_spi/display.py +6 -2
- esphome/components/ssd1331_spi/display.py +6 -2
- esphome/components/ssd1351_spi/display.py +6 -2
- esphome/components/st7567_spi/display.py +6 -2
- esphome/components/st7701s/display.py +5 -1
- esphome/components/st7735/display.py +10 -5
- esphome/components/st7789v/display.py +12 -7
- esphome/components/statsd/statsd.cpp +2 -0
- esphome/components/statsd/statsd.h +2 -0
- esphome/components/sun/sun.h +3 -0
- esphome/components/tc74/__init__.py +1 -0
- esphome/components/tc74/sensor.py +32 -0
- esphome/components/tc74/tc74.cpp +68 -0
- esphome/components/tc74/tc74.h +28 -0
- esphome/components/touchscreen/__init__.py +41 -50
- esphome/components/touchscreen/touchscreen.h +4 -8
- esphome/components/tuya/fan/tuya_fan.cpp +1 -1
- esphome/components/udp/udp_component.cpp +6 -3
- esphome/components/udp/udp_component.h +4 -2
- esphome/components/waveshare_epaper/display.py +6 -2
- esphome/components/web_server/web_server.cpp +22 -0
- esphome/components/web_server/web_server.h +3 -0
- esphome/components/weikai/weikai.h +2 -2
- esphome/components/wifi/wifi_component.cpp +2 -2
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +4 -4
- esphome/components/wifi/wifi_component_esp8266.cpp +4 -4
- esphome/components/wifi/wifi_component_esp_idf.cpp +2 -2
- esphome/components/xpt2046/touchscreen/__init__.py +7 -32
- esphome/config_validation.py +3 -1
- esphome/const.py +9 -2
- esphome/core/defines.h +8 -2
- esphome/core/helpers.cpp +32 -17
- esphome/core/helpers.h +32 -16
- esphome/core/ring_buffer.cpp +2 -2
- esphome/core/ring_buffer.h +2 -2
- esphome/dashboard/core.py +25 -0
- esphome/dashboard/status/mdns.py +3 -4
- esphome/dashboard/web_server.py +54 -19
- esphome/espota2.py +36 -35
- esphome/helpers.py +68 -16
- esphome/mqtt.py +9 -2
- esphome/storage_json.py +4 -0
- esphome/writer.py +7 -18
- esphome/zeroconf.py +8 -6
- {esphome-2024.10.3.dist-info → esphome-2024.11.0.dist-info}/METADATA +7 -5
- {esphome-2024.10.3.dist-info → esphome-2024.11.0.dist-info}/RECORD +232 -186
- esphome/core/bytebuffer.cpp +0 -167
- esphome/core/bytebuffer.h +0 -144
- /esphome/components/{qspi_amoled → qspi_dbi}/__init__.py +0 -0
- {esphome-2024.10.3.dist-info → esphome-2024.11.0.dist-info}/LICENSE +0 -0
- {esphome-2024.10.3.dist-info → esphome-2024.11.0.dist-info}/WHEEL +0 -0
- {esphome-2024.10.3.dist-info → esphome-2024.11.0.dist-info}/entry_points.txt +0 -0
- {esphome-2024.10.3.dist-info → esphome-2024.11.0.dist-info}/top_level.txt +0 -0
@@ -25,6 +25,8 @@ from .const import (
|
|
25
25
|
CONF_MODBUS_CONTROLLER_ID,
|
26
26
|
CONF_OFFLINE_SKIP_UPDATES,
|
27
27
|
CONF_ON_COMMAND_SENT,
|
28
|
+
CONF_ON_ONLINE,
|
29
|
+
CONF_ON_OFFLINE,
|
28
30
|
CONF_REGISTER_COUNT,
|
29
31
|
CONF_REGISTER_TYPE,
|
30
32
|
CONF_RESPONSE_SIZE,
|
@@ -114,6 +116,14 @@ ModbusCommandSentTrigger = modbus_controller_ns.class_(
|
|
114
116
|
"ModbusCommandSentTrigger", automation.Trigger.template(cg.int_, cg.int_)
|
115
117
|
)
|
116
118
|
|
119
|
+
ModbusOnlineTrigger = modbus_controller_ns.class_(
|
120
|
+
"ModbusOnlineTrigger", automation.Trigger.template(cg.int_, cg.int_)
|
121
|
+
)
|
122
|
+
|
123
|
+
ModbusOfflineTrigger = modbus_controller_ns.class_(
|
124
|
+
"ModbusOfflineTrigger", automation.Trigger.template(cg.int_, cg.int_)
|
125
|
+
)
|
126
|
+
|
117
127
|
_LOGGER = logging.getLogger(__name__)
|
118
128
|
|
119
129
|
ModbusServerRegisterSchema = cv.Schema(
|
@@ -146,6 +156,16 @@ CONFIG_SCHEMA = cv.All(
|
|
146
156
|
),
|
147
157
|
}
|
148
158
|
),
|
159
|
+
cv.Optional(CONF_ON_ONLINE): automation.validate_automation(
|
160
|
+
{
|
161
|
+
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ModbusOnlineTrigger),
|
162
|
+
}
|
163
|
+
),
|
164
|
+
cv.Optional(CONF_ON_OFFLINE): automation.validate_automation(
|
165
|
+
{
|
166
|
+
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ModbusOnlineTrigger),
|
167
|
+
}
|
168
|
+
),
|
149
169
|
}
|
150
170
|
)
|
151
171
|
.extend(cv.polling_component_schema("60s"))
|
@@ -284,7 +304,17 @@ async def to_code(config):
|
|
284
304
|
for conf in config.get(CONF_ON_COMMAND_SENT, []):
|
285
305
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
286
306
|
await automation.build_automation(
|
287
|
-
trigger, [(
|
307
|
+
trigger, [(cg.int_, "function_code"), (cg.int_, "address")], conf
|
308
|
+
)
|
309
|
+
for conf in config.get(CONF_ON_ONLINE, []):
|
310
|
+
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
311
|
+
await automation.build_automation(
|
312
|
+
trigger, [(cg.int_, "function_code"), (cg.int_, "address")], conf
|
313
|
+
)
|
314
|
+
for conf in config.get(CONF_ON_OFFLINE, []):
|
315
|
+
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
316
|
+
await automation.build_automation(
|
317
|
+
trigger, [(cg.int_, "function_code"), (cg.int_, "address")], conf
|
288
318
|
)
|
289
319
|
|
290
320
|
|
@@ -15,5 +15,21 @@ class ModbusCommandSentTrigger : public Trigger<int, int> {
|
|
15
15
|
}
|
16
16
|
};
|
17
17
|
|
18
|
+
class ModbusOnlineTrigger : public Trigger<int, int> {
|
19
|
+
public:
|
20
|
+
ModbusOnlineTrigger(ModbusController *a_modbuscontroller) {
|
21
|
+
a_modbuscontroller->add_on_online_callback(
|
22
|
+
[this](int function_code, int address) { this->trigger(function_code, address); });
|
23
|
+
}
|
24
|
+
};
|
25
|
+
|
26
|
+
class ModbusOfflineTrigger : public Trigger<int, int> {
|
27
|
+
public:
|
28
|
+
ModbusOfflineTrigger(ModbusController *a_modbuscontroller) {
|
29
|
+
a_modbuscontroller->add_on_offline_callback(
|
30
|
+
[this](int function_code, int address) { this->trigger(function_code, address); });
|
31
|
+
}
|
32
|
+
};
|
33
|
+
|
18
34
|
} // namespace modbus_controller
|
19
35
|
} // namespace esphome
|
@@ -9,6 +9,8 @@ CONF_MAX_CMD_RETRIES = "max_cmd_retries"
|
|
9
9
|
CONF_MODBUS_CONTROLLER_ID = "modbus_controller_id"
|
10
10
|
CONF_MODBUS_FUNCTIONCODE = "modbus_functioncode"
|
11
11
|
CONF_ON_COMMAND_SENT = "on_command_sent"
|
12
|
+
CONF_ON_ONLINE = "on_online"
|
13
|
+
CONF_ON_OFFLINE = "on_offline"
|
12
14
|
CONF_RAW_ENCODE = "raw_encode"
|
13
15
|
CONF_REGISTER_COUNT = "register_count"
|
14
16
|
CONF_REGISTER_TYPE = "register_type"
|
@@ -32,8 +32,10 @@ bool ModbusController::send_next_command_() {
|
|
32
32
|
r.skip_updates_counter = this->offline_skip_updates_;
|
33
33
|
}
|
34
34
|
}
|
35
|
+
|
36
|
+
this->module_offline_ = true;
|
37
|
+
this->offline_callback_.call((int) command->function_code, command->register_address);
|
35
38
|
}
|
36
|
-
this->module_offline_ = true;
|
37
39
|
ESP_LOGD(TAG, "Modbus command to device=%d register=0x%02X no response received - removed from send queue",
|
38
40
|
this->address_, command->register_address);
|
39
41
|
this->command_queue_.pop_front();
|
@@ -68,8 +70,10 @@ void ModbusController::on_modbus_data(const std::vector<uint8_t> &data) {
|
|
68
70
|
r.skip_updates_counter = 0;
|
69
71
|
}
|
70
72
|
}
|
73
|
+
// Restore module online state
|
74
|
+
this->module_offline_ = false;
|
75
|
+
this->online_callback_.call((int) current_command->function_code, current_command->register_address);
|
71
76
|
}
|
72
|
-
this->module_offline_ = false;
|
73
77
|
|
74
78
|
// Move the commandItem to the response queue
|
75
79
|
current_command->payload = data;
|
@@ -670,5 +674,13 @@ void ModbusController::add_on_command_sent_callback(std::function<void(int, int)
|
|
670
674
|
this->command_sent_callback_.add(std::move(callback));
|
671
675
|
}
|
672
676
|
|
677
|
+
void ModbusController::add_on_online_callback(std::function<void(int, int)> &&callback) {
|
678
|
+
this->online_callback_.add(std::move(callback));
|
679
|
+
}
|
680
|
+
|
681
|
+
void ModbusController::add_on_offline_callback(std::function<void(int, int)> &&callback) {
|
682
|
+
this->offline_callback_.add(std::move(callback));
|
683
|
+
}
|
684
|
+
|
673
685
|
} // namespace modbus_controller
|
674
686
|
} // namespace esphome
|
@@ -468,6 +468,10 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice {
|
|
468
468
|
bool get_module_offline() { return module_offline_; }
|
469
469
|
/// Set callback for commands
|
470
470
|
void add_on_command_sent_callback(std::function<void(int, int)> &&callback);
|
471
|
+
/// Set callback for online changes
|
472
|
+
void add_on_online_callback(std::function<void(int, int)> &&callback);
|
473
|
+
/// Set callback for offline changes
|
474
|
+
void add_on_offline_callback(std::function<void(int, int)> &&callback);
|
471
475
|
/// called by esphome generated code to set the max_cmd_retries.
|
472
476
|
void set_max_cmd_retries(uint8_t max_cmd_retries) { this->max_cmd_retries_ = max_cmd_retries; }
|
473
477
|
/// get how many times a command will be (re)sent if no response is received
|
@@ -508,7 +512,12 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice {
|
|
508
512
|
uint16_t offline_skip_updates_;
|
509
513
|
/// How many times we will retry a command if we get no response
|
510
514
|
uint8_t max_cmd_retries_{4};
|
515
|
+
/// Command sent callback
|
511
516
|
CallbackManager<void(int, int)> command_sent_callback_{};
|
517
|
+
/// Server online callback
|
518
|
+
CallbackManager<void(int, int)> online_callback_{};
|
519
|
+
/// Server offline callback
|
520
|
+
CallbackManager<void(int, int)> offline_callback_{};
|
512
521
|
};
|
513
522
|
|
514
523
|
/** Convert vector<uint8_t> response payload to float.
|
@@ -17,6 +17,8 @@ void MopekaProCheck::dump_config() {
|
|
17
17
|
LOG_SENSOR(" ", "Temperature", this->temperature_);
|
18
18
|
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
|
19
19
|
LOG_SENSOR(" ", "Reading Distance", this->distance_);
|
20
|
+
LOG_SENSOR(" ", "Read Quality", this->read_quality_);
|
21
|
+
LOG_SENSOR(" ", "Ignored Reads", this->ignored_reads_);
|
20
22
|
}
|
21
23
|
|
22
24
|
/**
|
@@ -66,34 +68,49 @@ bool MopekaProCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
|
66
68
|
this->battery_level_->publish_state(level);
|
67
69
|
}
|
68
70
|
|
71
|
+
// Get the quality value
|
72
|
+
SensorReadQuality quality_value = this->parse_read_quality_(manu_data.data);
|
73
|
+
if (this->read_quality_ != nullptr) {
|
74
|
+
this->read_quality_->publish_state(static_cast<int>(quality_value));
|
75
|
+
}
|
76
|
+
|
77
|
+
// Determine if we have a good enough quality of read to report level and distance
|
78
|
+
// sensors. This sensor is reported regardless of distance or level sensors being enabled
|
79
|
+
if (quality_value < this->min_signal_quality_) {
|
80
|
+
ESP_LOGW(TAG, "Read Quality too low to report distance or level");
|
81
|
+
this->ignored_read_count_++;
|
82
|
+
} else {
|
83
|
+
// reset to zero since read quality was sufficient
|
84
|
+
this->ignored_read_count_ = 0;
|
85
|
+
}
|
86
|
+
// Report number of contiguous ignored reads if sensor defined
|
87
|
+
if (this->ignored_reads_ != nullptr) {
|
88
|
+
this->ignored_reads_->publish_state(this->ignored_read_count_);
|
89
|
+
}
|
90
|
+
|
69
91
|
// Get distance and level if either are sensors
|
70
92
|
if ((this->distance_ != nullptr) || (this->level_ != nullptr)) {
|
71
93
|
uint32_t distance_value = this->parse_distance_(manu_data.data);
|
72
|
-
SensorReadQuality quality_value = this->parse_read_quality_(manu_data.data);
|
73
94
|
ESP_LOGD(TAG, "Distance Sensor: Quality (0x%X) Distance (%" PRId32 "mm)", quality_value, distance_value);
|
74
|
-
if (quality_value < QUALITY_HIGH) {
|
75
|
-
ESP_LOGW(TAG, "Poor read quality.");
|
76
|
-
}
|
77
|
-
if (quality_value < QUALITY_MED) {
|
78
|
-
// if really bad reading set to 0
|
79
|
-
ESP_LOGW(TAG, "Setting distance to 0");
|
80
|
-
distance_value = 0;
|
81
|
-
}
|
82
95
|
|
83
|
-
// update distance
|
84
|
-
if
|
85
|
-
|
86
|
-
|
96
|
+
// only update distance and level sensors if read quality was sufficient. This can be determined by
|
97
|
+
// if the ignored_read_count is zero.
|
98
|
+
if (this->ignored_read_count_ == 0) {
|
99
|
+
// update distance sensor
|
100
|
+
if (this->distance_ != nullptr) {
|
101
|
+
this->distance_->publish_state(distance_value);
|
102
|
+
}
|
87
103
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
104
|
+
// update level sensor
|
105
|
+
if (this->level_ != nullptr) {
|
106
|
+
uint8_t tank_level = 0;
|
107
|
+
if (distance_value >= this->full_mm_) {
|
108
|
+
tank_level = 100; // cap at 100%
|
109
|
+
} else if (distance_value > this->empty_mm_) {
|
110
|
+
tank_level = ((100.0f / (this->full_mm_ - this->empty_mm_)) * (distance_value - this->empty_mm_));
|
111
|
+
}
|
112
|
+
this->level_->publish_state(tank_level);
|
95
113
|
}
|
96
|
-
this->level_->publish_state(tank_level);
|
97
114
|
}
|
98
115
|
}
|
99
116
|
|
@@ -131,6 +148,8 @@ uint32_t MopekaProCheck::parse_distance_(const std::vector<uint8_t> &message) {
|
|
131
148
|
uint8_t MopekaProCheck::parse_temperature_(const std::vector<uint8_t> &message) { return (message[2] & 0x7F) - 40; }
|
132
149
|
|
133
150
|
SensorReadQuality MopekaProCheck::parse_read_quality_(const std::vector<uint8_t> &message) {
|
151
|
+
// Since a 8 bit value is being shifted and truncated to 2 bits all possible values are defined as enumeration
|
152
|
+
// value and the static cast is safe.
|
134
153
|
return static_cast<SensorReadQuality>(message[4] >> 6);
|
135
154
|
}
|
136
155
|
|
@@ -24,9 +24,9 @@ enum SensorType {
|
|
24
24
|
};
|
25
25
|
|
26
26
|
// Sensor read quality. If sensor is poorly placed or tank level
|
27
|
-
// gets too low the read quality will show and the
|
27
|
+
// gets too low the read quality will show and the distance
|
28
28
|
// measurement may be inaccurate.
|
29
|
-
enum SensorReadQuality { QUALITY_HIGH = 0x3, QUALITY_MED = 0x2, QUALITY_LOW = 0x1,
|
29
|
+
enum SensorReadQuality { QUALITY_HIGH = 0x3, QUALITY_MED = 0x2, QUALITY_LOW = 0x1, QUALITY_ZERO = 0x0 };
|
30
30
|
|
31
31
|
class MopekaProCheck : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
|
32
32
|
public:
|
@@ -35,11 +35,14 @@ class MopekaProCheck : public Component, public esp32_ble_tracker::ESPBTDeviceLi
|
|
35
35
|
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
|
36
36
|
void dump_config() override;
|
37
37
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
38
|
+
void set_min_signal_quality(SensorReadQuality min) { this->min_signal_quality_ = min; };
|
38
39
|
|
39
40
|
void set_level(sensor::Sensor *level) { level_ = level; };
|
40
41
|
void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; };
|
41
42
|
void set_battery_level(sensor::Sensor *bat) { battery_level_ = bat; };
|
42
43
|
void set_distance(sensor::Sensor *distance) { distance_ = distance; };
|
44
|
+
void set_signal_quality(sensor::Sensor *rq) { read_quality_ = rq; };
|
45
|
+
void set_ignored_reads(sensor::Sensor *ir) { ignored_reads_ = ir; };
|
43
46
|
void set_tank_full(float full) { full_mm_ = full; };
|
44
47
|
void set_tank_empty(float empty) { empty_mm_ = empty; };
|
45
48
|
|
@@ -49,9 +52,13 @@ class MopekaProCheck : public Component, public esp32_ble_tracker::ESPBTDeviceLi
|
|
49
52
|
sensor::Sensor *temperature_{nullptr};
|
50
53
|
sensor::Sensor *distance_{nullptr};
|
51
54
|
sensor::Sensor *battery_level_{nullptr};
|
55
|
+
sensor::Sensor *read_quality_{nullptr};
|
56
|
+
sensor::Sensor *ignored_reads_{nullptr};
|
52
57
|
|
53
58
|
uint32_t full_mm_;
|
54
59
|
uint32_t empty_mm_;
|
60
|
+
uint32_t ignored_read_count_ = 0;
|
61
|
+
SensorReadQuality min_signal_quality_ = QUALITY_MED;
|
55
62
|
|
56
63
|
uint8_t parse_battery_level_(const std::vector<uint8_t> &message);
|
57
64
|
uint32_t parse_distance_(const std::vector<uint8_t> &message);
|
@@ -5,9 +5,12 @@ from esphome.const import (
|
|
5
5
|
CONF_DISTANCE,
|
6
6
|
CONF_MAC_ADDRESS,
|
7
7
|
CONF_ID,
|
8
|
+
ICON_COUNTER,
|
8
9
|
ICON_THERMOMETER,
|
9
10
|
ICON_RULER,
|
11
|
+
ICON_SIGNAL,
|
10
12
|
UNIT_PERCENT,
|
13
|
+
UNIT_EMPTY,
|
11
14
|
CONF_LEVEL,
|
12
15
|
CONF_TEMPERATURE,
|
13
16
|
DEVICE_CLASS_TEMPERATURE,
|
@@ -16,11 +19,15 @@ from esphome.const import (
|
|
16
19
|
STATE_CLASS_MEASUREMENT,
|
17
20
|
CONF_BATTERY_LEVEL,
|
18
21
|
DEVICE_CLASS_BATTERY,
|
22
|
+
ENTITY_CATEGORY_DIAGNOSTIC,
|
19
23
|
)
|
20
24
|
|
21
25
|
CONF_TANK_TYPE = "tank_type"
|
22
26
|
CONF_CUSTOM_DISTANCE_FULL = "custom_distance_full"
|
23
27
|
CONF_CUSTOM_DISTANCE_EMPTY = "custom_distance_empty"
|
28
|
+
CONF_SIGNAL_QUALITY = "signal_quality"
|
29
|
+
CONF_MINIMUM_SIGNAL_QUALITY = "minimum_signal_quality"
|
30
|
+
CONF_IGNORED_READS = "ignored_reads"
|
24
31
|
|
25
32
|
ICON_PROPANE_TANK = "mdi:propane-tank"
|
26
33
|
|
@@ -56,6 +63,14 @@ MopekaProCheck = mopeka_pro_check_ns.class_(
|
|
56
63
|
"MopekaProCheck", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
|
57
64
|
)
|
58
65
|
|
66
|
+
SensorReadQuality = mopeka_pro_check_ns.enum("SensorReadQuality")
|
67
|
+
SIGNAL_QUALITIES = {
|
68
|
+
"ZERO": SensorReadQuality.QUALITY_ZERO,
|
69
|
+
"LOW": SensorReadQuality.QUALITY_LOW,
|
70
|
+
"MEDIUM": SensorReadQuality.QUALITY_MED,
|
71
|
+
"HIGH": SensorReadQuality.QUALITY_HIGH,
|
72
|
+
}
|
73
|
+
|
59
74
|
CONFIG_SCHEMA = (
|
60
75
|
cv.Schema(
|
61
76
|
{
|
@@ -89,6 +104,21 @@ CONFIG_SCHEMA = (
|
|
89
104
|
device_class=DEVICE_CLASS_BATTERY,
|
90
105
|
state_class=STATE_CLASS_MEASUREMENT,
|
91
106
|
),
|
107
|
+
cv.Optional(CONF_SIGNAL_QUALITY): sensor.sensor_schema(
|
108
|
+
unit_of_measurement=UNIT_EMPTY,
|
109
|
+
icon=ICON_SIGNAL,
|
110
|
+
accuracy_decimals=0,
|
111
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
112
|
+
),
|
113
|
+
cv.Optional(CONF_IGNORED_READS): sensor.sensor_schema(
|
114
|
+
unit_of_measurement=UNIT_EMPTY,
|
115
|
+
icon=ICON_COUNTER,
|
116
|
+
accuracy_decimals=0,
|
117
|
+
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
118
|
+
),
|
119
|
+
cv.Optional(CONF_MINIMUM_SIGNAL_QUALITY, default="MEDIUM"): cv.enum(
|
120
|
+
SIGNAL_QUALITIES, upper=True
|
121
|
+
),
|
92
122
|
}
|
93
123
|
)
|
94
124
|
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
|
@@ -119,6 +149,11 @@ async def to_code(config):
|
|
119
149
|
cg.add(var.set_tank_empty(CONF_SUPPORTED_TANKS_MAP[t][0]))
|
120
150
|
cg.add(var.set_tank_full(CONF_SUPPORTED_TANKS_MAP[t][1]))
|
121
151
|
|
152
|
+
if (
|
153
|
+
minimum_signal_quality := config.get(CONF_MINIMUM_SIGNAL_QUALITY, None)
|
154
|
+
) is not None:
|
155
|
+
cg.add(var.set_min_signal_quality(minimum_signal_quality))
|
156
|
+
|
122
157
|
if CONF_TEMPERATURE in config:
|
123
158
|
sens = await sensor.new_sensor(config[CONF_TEMPERATURE])
|
124
159
|
cg.add(var.set_temperature(sens))
|
@@ -131,3 +166,9 @@ async def to_code(config):
|
|
131
166
|
if CONF_BATTERY_LEVEL in config:
|
132
167
|
sens = await sensor.new_sensor(config[CONF_BATTERY_LEVEL])
|
133
168
|
cg.add(var.set_battery_level(sens))
|
169
|
+
if CONF_SIGNAL_QUALITY in config:
|
170
|
+
sens = await sensor.new_sensor(config[CONF_SIGNAL_QUALITY])
|
171
|
+
cg.add(var.set_signal_quality(sens))
|
172
|
+
if CONF_IGNORED_READS in config:
|
173
|
+
sens = await sensor.new_sensor(config[CONF_IGNORED_READS])
|
174
|
+
cg.add(var.set_ignored_reads(sens))
|
@@ -22,6 +22,7 @@ from esphome.const import (
|
|
22
22
|
CONF_DISCOVERY_PREFIX,
|
23
23
|
CONF_DISCOVERY_RETAIN,
|
24
24
|
CONF_DISCOVERY_UNIQUE_ID_GENERATOR,
|
25
|
+
CONF_ENABLE_ON_BOOT,
|
25
26
|
CONF_ID,
|
26
27
|
CONF_KEEPALIVE,
|
27
28
|
CONF_LEVEL,
|
@@ -41,6 +42,7 @@ from esphome.const import (
|
|
41
42
|
CONF_SHUTDOWN_MESSAGE,
|
42
43
|
CONF_SSL_FINGERPRINTS,
|
43
44
|
CONF_STATE_TOPIC,
|
45
|
+
CONF_SUBSCRIBE_QOS,
|
44
46
|
CONF_TOPIC,
|
45
47
|
CONF_TOPIC_PREFIX,
|
46
48
|
CONF_TRIGGER_ID,
|
@@ -98,6 +100,8 @@ MQTTMessage = mqtt_ns.struct("MQTTMessage")
|
|
98
100
|
MQTTClientComponent = mqtt_ns.class_("MQTTClientComponent", cg.Component)
|
99
101
|
MQTTPublishAction = mqtt_ns.class_("MQTTPublishAction", automation.Action)
|
100
102
|
MQTTPublishJsonAction = mqtt_ns.class_("MQTTPublishJsonAction", automation.Action)
|
103
|
+
MQTTEnableAction = mqtt_ns.class_("MQTTEnableAction", automation.Action)
|
104
|
+
MQTTDisableAction = mqtt_ns.class_("MQTTDisableAction", automation.Action)
|
101
105
|
MQTTMessageTrigger = mqtt_ns.class_(
|
102
106
|
"MQTTMessageTrigger", automation.Trigger.template(cg.std_string), cg.Component
|
103
107
|
)
|
@@ -207,6 +211,7 @@ CONFIG_SCHEMA = cv.All(
|
|
207
211
|
{
|
208
212
|
cv.GenerateID(): cv.declare_id(MQTTClientComponent),
|
209
213
|
cv.Required(CONF_BROKER): cv.string_strict,
|
214
|
+
cv.Optional(CONF_ENABLE_ON_BOOT, default=True): cv.boolean,
|
210
215
|
cv.Optional(CONF_PORT, default=1883): cv.port,
|
211
216
|
cv.Optional(CONF_USERNAME, default=""): cv.string,
|
212
217
|
cv.Optional(CONF_PASSWORD, default=""): cv.string,
|
@@ -324,6 +329,7 @@ async def to_code(config):
|
|
324
329
|
cg.add_global(mqtt_ns.using)
|
325
330
|
|
326
331
|
cg.add(var.set_broker_address(config[CONF_BROKER]))
|
332
|
+
cg.add(var.set_enable_on_boot(config[CONF_ENABLE_ON_BOOT]))
|
327
333
|
cg.add(var.set_broker_port(config[CONF_PORT]))
|
328
334
|
cg.add(var.set_username(config[CONF_USERNAME]))
|
329
335
|
cg.add(var.set_password(config[CONF_PASSWORD]))
|
@@ -518,6 +524,8 @@ async def register_mqtt_component(var, config):
|
|
518
524
|
cg.add(var.set_qos(config[CONF_QOS]))
|
519
525
|
if CONF_RETAIN in config:
|
520
526
|
cg.add(var.set_retain(config[CONF_RETAIN]))
|
527
|
+
if CONF_SUBSCRIBE_QOS in config:
|
528
|
+
cg.add(var.set_subscribe_qos(config[CONF_SUBSCRIBE_QOS]))
|
521
529
|
if not config.get(CONF_DISCOVERY, True):
|
522
530
|
cg.add(var.disable_discovery())
|
523
531
|
if CONF_STATE_TOPIC in config:
|
@@ -552,3 +560,31 @@ async def register_mqtt_component(var, config):
|
|
552
560
|
async def mqtt_connected_to_code(config, condition_id, template_arg, args):
|
553
561
|
paren = await cg.get_variable(config[CONF_ID])
|
554
562
|
return cg.new_Pvariable(condition_id, template_arg, paren)
|
563
|
+
|
564
|
+
|
565
|
+
@automation.register_action(
|
566
|
+
"mqtt.enable",
|
567
|
+
MQTTEnableAction,
|
568
|
+
cv.Schema(
|
569
|
+
{
|
570
|
+
cv.GenerateID(): cv.use_id(MQTTClientComponent),
|
571
|
+
}
|
572
|
+
),
|
573
|
+
)
|
574
|
+
async def mqtt_enable_to_code(config, action_id, template_arg, args):
|
575
|
+
paren = await cg.get_variable(config[CONF_ID])
|
576
|
+
return cg.new_Pvariable(action_id, template_arg, paren)
|
577
|
+
|
578
|
+
|
579
|
+
@automation.register_action(
|
580
|
+
"mqtt.disable",
|
581
|
+
MQTTDisableAction,
|
582
|
+
cv.Schema(
|
583
|
+
{
|
584
|
+
cv.GenerateID(): cv.use_id(MQTTClientComponent),
|
585
|
+
}
|
586
|
+
),
|
587
|
+
)
|
588
|
+
async def mqtt_disable_to_code(config, action_id, template_arg, args):
|
589
|
+
paren = await cg.get_variable(config[CONF_ID])
|
590
|
+
return cg.new_Pvariable(action_id, template_arg, paren)
|
@@ -50,6 +50,8 @@ void MQTTClientComponent::setup() {
|
|
50
50
|
}
|
51
51
|
});
|
52
52
|
this->mqtt_backend_.set_on_disconnect([this](MQTTClientDisconnectReason reason) {
|
53
|
+
if (this->state_ == MQTT_CLIENT_DISABLED)
|
54
|
+
return;
|
53
55
|
this->state_ = MQTT_CLIENT_DISCONNECTED;
|
54
56
|
this->disconnect_reason_ = reason;
|
55
57
|
});
|
@@ -77,8 +79,9 @@ void MQTTClientComponent::setup() {
|
|
77
79
|
topic, [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, 2);
|
78
80
|
}
|
79
81
|
|
80
|
-
this->
|
81
|
-
|
82
|
+
if (this->enable_on_boot_) {
|
83
|
+
this->enable();
|
84
|
+
}
|
82
85
|
}
|
83
86
|
|
84
87
|
void MQTTClientComponent::send_device_info_() {
|
@@ -163,7 +166,9 @@ void MQTTClientComponent::dump_config() {
|
|
163
166
|
ESP_LOGCONFIG(TAG, " Availability: '%s'", this->availability_.topic.c_str());
|
164
167
|
}
|
165
168
|
}
|
166
|
-
bool MQTTClientComponent::can_proceed() {
|
169
|
+
bool MQTTClientComponent::can_proceed() {
|
170
|
+
return network::is_disabled() || this->state_ == MQTT_CLIENT_DISABLED || this->is_connected();
|
171
|
+
}
|
167
172
|
|
168
173
|
void MQTTClientComponent::start_dnslookup_() {
|
169
174
|
for (auto &subscription : this->subscriptions_) {
|
@@ -339,6 +344,8 @@ void MQTTClientComponent::loop() {
|
|
339
344
|
const uint32_t now = millis();
|
340
345
|
|
341
346
|
switch (this->state_) {
|
347
|
+
case MQTT_CLIENT_DISABLED:
|
348
|
+
return; // Return to avoid a reboot when disabled
|
342
349
|
case MQTT_CLIENT_DISCONNECTED:
|
343
350
|
if (now - this->connect_begin_ > 5000) {
|
344
351
|
this->start_dnslookup_();
|
@@ -501,6 +508,23 @@ bool MQTTClientComponent::publish_json(const std::string &topic, const json::jso
|
|
501
508
|
return this->publish(topic, message, qos, retain);
|
502
509
|
}
|
503
510
|
|
511
|
+
void MQTTClientComponent::enable() {
|
512
|
+
if (this->state_ != MQTT_CLIENT_DISABLED)
|
513
|
+
return;
|
514
|
+
ESP_LOGD(TAG, "Enabling MQTT...");
|
515
|
+
this->state_ = MQTT_CLIENT_DISCONNECTED;
|
516
|
+
this->last_connected_ = millis();
|
517
|
+
this->start_dnslookup_();
|
518
|
+
}
|
519
|
+
|
520
|
+
void MQTTClientComponent::disable() {
|
521
|
+
if (this->state_ == MQTT_CLIENT_DISABLED)
|
522
|
+
return;
|
523
|
+
ESP_LOGD(TAG, "Disabling MQTT...");
|
524
|
+
this->state_ = MQTT_CLIENT_DISABLED;
|
525
|
+
this->on_shutdown();
|
526
|
+
}
|
527
|
+
|
504
528
|
/** Check if the message topic matches the given subscription topic
|
505
529
|
*
|
506
530
|
* INFO: MQTT spec mandates that topics must not be empty and must be valid NULL-terminated UTF-8 strings.
|
@@ -87,7 +87,8 @@ struct MQTTDiscoveryInfo {
|
|
87
87
|
};
|
88
88
|
|
89
89
|
enum MQTTClientState {
|
90
|
-
|
90
|
+
MQTT_CLIENT_DISABLED = 0,
|
91
|
+
MQTT_CLIENT_DISCONNECTED,
|
91
92
|
MQTT_CLIENT_RESOLVING_ADDRESS,
|
92
93
|
MQTT_CLIENT_CONNECTING,
|
93
94
|
MQTT_CLIENT_CONNECTED,
|
@@ -247,6 +248,9 @@ class MQTTClientComponent : public Component {
|
|
247
248
|
void register_mqtt_component(MQTTComponent *component);
|
248
249
|
|
249
250
|
bool is_connected();
|
251
|
+
void set_enable_on_boot(bool enable_on_boot) { this->enable_on_boot_ = enable_on_boot; }
|
252
|
+
void enable();
|
253
|
+
void disable();
|
250
254
|
|
251
255
|
void on_shutdown() override;
|
252
256
|
|
@@ -314,10 +318,11 @@ class MQTTClientComponent : public Component {
|
|
314
318
|
MQTTBackendLibreTiny mqtt_backend_;
|
315
319
|
#endif
|
316
320
|
|
317
|
-
MQTTClientState state_{
|
321
|
+
MQTTClientState state_{MQTT_CLIENT_DISABLED};
|
318
322
|
network::IPAddress ip_;
|
319
323
|
bool dns_resolved_{false};
|
320
324
|
bool dns_resolve_error_{false};
|
325
|
+
bool enable_on_boot_{true};
|
321
326
|
std::vector<MQTTComponent *> children_;
|
322
327
|
uint32_t reboot_timeout_{300000};
|
323
328
|
uint32_t connect_begin_;
|
@@ -414,6 +419,26 @@ template<typename... Ts> class MQTTConnectedCondition : public Condition<Ts...>
|
|
414
419
|
MQTTClientComponent *parent_;
|
415
420
|
};
|
416
421
|
|
422
|
+
template<typename... Ts> class MQTTEnableAction : public Action<Ts...> {
|
423
|
+
public:
|
424
|
+
MQTTEnableAction(MQTTClientComponent *parent) : parent_(parent) {}
|
425
|
+
|
426
|
+
void play(Ts... x) override { this->parent_->enable(); }
|
427
|
+
|
428
|
+
protected:
|
429
|
+
MQTTClientComponent *parent_;
|
430
|
+
};
|
431
|
+
|
432
|
+
template<typename... Ts> class MQTTDisableAction : public Action<Ts...> {
|
433
|
+
public:
|
434
|
+
MQTTDisableAction(MQTTClientComponent *parent) : parent_(parent) {}
|
435
|
+
|
436
|
+
void play(Ts... x) override { this->parent_->disable(); }
|
437
|
+
|
438
|
+
protected:
|
439
|
+
MQTTClientComponent *parent_;
|
440
|
+
};
|
441
|
+
|
417
442
|
} // namespace mqtt
|
418
443
|
} // namespace esphome
|
419
444
|
|
@@ -71,8 +71,10 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo
|
|
71
71
|
root[MQTT_MIN_TEMP] = traits.get_visual_min_temperature();
|
72
72
|
// max_temp
|
73
73
|
root[MQTT_MAX_TEMP] = traits.get_visual_max_temperature();
|
74
|
-
//
|
75
|
-
root[
|
74
|
+
// target_temp_step
|
75
|
+
root[MQTT_TARGET_TEMPERATURE_STEP] = traits.get_visual_target_temperature_step();
|
76
|
+
// current_temp_step
|
77
|
+
root[MQTT_CURRENT_TEMPERATURE_STEP] = traits.get_visual_current_temperature_step();
|
76
78
|
// temperature units are always coerced to Celsius internally
|
77
79
|
root[MQTT_TEMPERATURE_UNIT] = "C";
|
78
80
|
|
@@ -16,6 +16,8 @@ static const char *const TAG = "mqtt.component";
|
|
16
16
|
|
17
17
|
void MQTTComponent::set_qos(uint8_t qos) { this->qos_ = qos; }
|
18
18
|
|
19
|
+
void MQTTComponent::set_subscribe_qos(uint8_t qos) { this->subscribe_qos_ = qos; }
|
20
|
+
|
19
21
|
void MQTTComponent::set_retain(bool retain) { this->retain_ = retain; }
|
20
22
|
|
21
23
|
std::string MQTTComponent::get_discovery_topic_(const MQTTDiscoveryInfo &discovery_info) const {
|
@@ -76,6 +78,10 @@ bool MQTTComponent::send_discovery_() {
|
|
76
78
|
config.command_topic = true;
|
77
79
|
|
78
80
|
this->send_discovery(root, config);
|
81
|
+
// Set subscription QoS (default is 0)
|
82
|
+
if (this->subscribe_qos_ != 0) {
|
83
|
+
root[MQTT_QOS] = this->subscribe_qos_;
|
84
|
+
}
|
79
85
|
|
80
86
|
// Fields from EntityBase
|
81
87
|
if (this->get_entity()->has_own_name()) {
|
@@ -89,6 +89,9 @@ class MQTTComponent : public Component {
|
|
89
89
|
void disable_discovery();
|
90
90
|
bool is_discovery_enabled() const;
|
91
91
|
|
92
|
+
/// Set the QOS for subscribe messages (used in discovery).
|
93
|
+
void set_subscribe_qos(uint8_t qos);
|
94
|
+
|
92
95
|
/// Override this method to return the component type (e.g. "light", "sensor", ...)
|
93
96
|
virtual std::string component_type() const = 0;
|
94
97
|
|
@@ -204,6 +207,7 @@ class MQTTComponent : public Component {
|
|
204
207
|
bool command_retain_{false};
|
205
208
|
bool retain_{true};
|
206
209
|
uint8_t qos_{0};
|
210
|
+
uint8_t subscribe_qos_{0};
|
207
211
|
bool discovery_enabled_{true};
|
208
212
|
bool resend_state_{false};
|
209
213
|
};
|
@@ -51,6 +51,7 @@ constexpr const char *const MQTT_COMMAND_TOPIC = "cmd_t";
|
|
51
51
|
constexpr const char *const MQTT_CONFIGURATION_URL = "cu";
|
52
52
|
constexpr const char *const MQTT_CURRENT_HUMIDITY_TEMPLATE = "curr_hum_tpl";
|
53
53
|
constexpr const char *const MQTT_CURRENT_HUMIDITY_TOPIC = "curr_hum_t";
|
54
|
+
constexpr const char *const MQTT_CURRENT_TEMPERATURE_STEP = "precision";
|
54
55
|
constexpr const char *const MQTT_CURRENT_TEMPERATURE_TEMPLATE = "curr_temp_tpl";
|
55
56
|
constexpr const char *const MQTT_CURRENT_TEMPERATURE_TOPIC = "curr_temp_t";
|
56
57
|
constexpr const char *const MQTT_DEVICE = "dev";
|
@@ -180,6 +181,7 @@ constexpr const char *const MQTT_PRESET_MODE_COMMAND_TOPIC = "pr_mode_cmd_t";
|
|
180
181
|
constexpr const char *const MQTT_PRESET_MODE_STATE_TOPIC = "pr_mode_stat_t";
|
181
182
|
constexpr const char *const MQTT_PRESET_MODE_VALUE_TEMPLATE = "pr_mode_val_tpl";
|
182
183
|
constexpr const char *const MQTT_PRESET_MODES = "pr_modes";
|
184
|
+
constexpr const char *const MQTT_QOS = "qos";
|
183
185
|
constexpr const char *const MQTT_RED_TEMPLATE = "r_tpl";
|
184
186
|
constexpr const char *const MQTT_RETAIN = "ret";
|
185
187
|
constexpr const char *const MQTT_RGB_COMMAND_TEMPLATE = "rgb_cmd_tpl";
|
@@ -231,6 +233,7 @@ constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TEMPLATE = "hum_cmd_tpl
|
|
231
233
|
constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TOPIC = "hum_cmd_t";
|
232
234
|
constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TEMPLATE = "hum_state_tpl";
|
233
235
|
constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TOPIC = "hum_stat_t";
|
236
|
+
constexpr const char *const MQTT_TARGET_TEMPERATURE_STEP = "temp_step";
|
234
237
|
constexpr const char *const MQTT_TEMPERATURE_COMMAND_TEMPLATE = "temp_cmd_tpl";
|
235
238
|
constexpr const char *const MQTT_TEMPERATURE_COMMAND_TOPIC = "temp_cmd_t";
|
236
239
|
constexpr const char *const MQTT_TEMPERATURE_HIGH_COMMAND_TEMPLATE = "temp_hi_cmd_tpl";
|
@@ -312,6 +315,7 @@ constexpr const char *const MQTT_COMMAND_TOPIC = "command_topic";
|
|
312
315
|
constexpr const char *const MQTT_CONFIGURATION_URL = "configuration_url";
|
313
316
|
constexpr const char *const MQTT_CURRENT_HUMIDITY_TEMPLATE = "current_humidity_template";
|
314
317
|
constexpr const char *const MQTT_CURRENT_HUMIDITY_TOPIC = "current_humidity_topic";
|
318
|
+
constexpr const char *const MQTT_CURRENT_TEMPERATURE_STEP = "precision";
|
315
319
|
constexpr const char *const MQTT_CURRENT_TEMPERATURE_TEMPLATE = "current_temperature_template";
|
316
320
|
constexpr const char *const MQTT_CURRENT_TEMPERATURE_TOPIC = "current_temperature_topic";
|
317
321
|
constexpr const char *const MQTT_DEVICE = "device";
|
@@ -441,6 +445,7 @@ constexpr const char *const MQTT_PRESET_MODE_COMMAND_TOPIC = "preset_mode_comman
|
|
441
445
|
constexpr const char *const MQTT_PRESET_MODE_STATE_TOPIC = "preset_mode_state_topic";
|
442
446
|
constexpr const char *const MQTT_PRESET_MODE_VALUE_TEMPLATE = "preset_mode_value_template";
|
443
447
|
constexpr const char *const MQTT_PRESET_MODES = "preset_modes";
|
448
|
+
constexpr const char *const MQTT_QOS = "qos";
|
444
449
|
constexpr const char *const MQTT_RED_TEMPLATE = "red_template";
|
445
450
|
constexpr const char *const MQTT_RETAIN = "retain";
|
446
451
|
constexpr const char *const MQTT_RGB_COMMAND_TEMPLATE = "rgb_command_template";
|
@@ -492,6 +497,7 @@ constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TEMPLATE = "target_humi
|
|
492
497
|
constexpr const char *const MQTT_TARGET_HUMIDITY_COMMAND_TOPIC = "target_humidity_command_topic";
|
493
498
|
constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TEMPLATE = "target_humidity_state_template";
|
494
499
|
constexpr const char *const MQTT_TARGET_HUMIDITY_STATE_TOPIC = "target_humidity_state_topic";
|
500
|
+
constexpr const char *const MQTT_TARGET_TEMPERATURE_STEP = "temp_step";
|
495
501
|
constexpr const char *const MQTT_TEMPERATURE_COMMAND_TEMPLATE = "temperature_command_template";
|
496
502
|
constexpr const char *const MQTT_TEMPERATURE_COMMAND_TOPIC = "temperature_command_topic";
|
497
503
|
constexpr const char *const MQTT_TEMPERATURE_HIGH_COMMAND_TEMPLATE = "temperature_high_command_template";
|