esphome 2024.9.2__py3-none-any.whl → 2024.10.0b1__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/components/aic3204/__init__.py +0 -0
- esphome/components/aic3204/aic3204.cpp +173 -0
- esphome/components/aic3204/aic3204.h +88 -0
- esphome/components/aic3204/audio_dac.py +52 -0
- esphome/components/aic3204/automation.h +23 -0
- esphome/components/alarm_control_panel/__init__.py +3 -4
- esphome/components/animation/__init__.py +16 -12
- esphome/components/api/api_connection.cpp +2 -0
- esphome/components/api/api_connection.h +3 -1
- esphome/components/api/api_frame_helper.cpp +2 -1
- esphome/components/api/api_frame_helper.h +2 -1
- esphome/components/api/api_server.cpp +2 -0
- esphome/components/api/api_server.h +3 -1
- esphome/components/api/custom_api_device.h +3 -2
- esphome/components/api/homeassistant_service.h +4 -3
- esphome/components/api/list_entities.cpp +2 -0
- esphome/components/api/list_entities.h +3 -2
- esphome/components/api/subscribe_state.cpp +2 -0
- esphome/components/api/subscribe_state.h +3 -2
- esphome/components/audio_dac/__init__.py +57 -0
- esphome/components/audio_dac/audio_dac.h +23 -0
- esphome/components/audio_dac/automation.h +43 -0
- esphome/components/bang_bang/bang_bang_climate.cpp +5 -2
- esphome/components/bedjet/bedjet_codec.cpp +4 -2
- esphome/components/binary_sensor/__init__.py +3 -4
- esphome/components/button/__init__.py +3 -4
- esphome/components/ch422g/__init__.py +26 -17
- esphome/components/ch422g/ch422g.cpp +66 -49
- esphome/components/ch422g/ch422g.h +17 -19
- esphome/components/climate/__init__.py +3 -4
- esphome/components/cover/__init__.py +4 -5
- esphome/components/cse7766/cse7766.cpp +11 -0
- esphome/components/cse7766/cse7766.h +4 -0
- esphome/components/cse7766/sensor.py +13 -1
- esphome/components/cst816/touchscreen/__init__.py +7 -4
- esphome/components/cst816/touchscreen/cst816_touchscreen.cpp +20 -19
- esphome/components/cst816/touchscreen/cst816_touchscreen.h +2 -0
- esphome/components/datetime/__init__.py +21 -14
- esphome/components/datetime/datetime_base.h +8 -1
- esphome/components/datetime/datetime_entity.cpp +2 -0
- esphome/components/datetime/datetime_entity.h +2 -0
- esphome/components/datetime/time_entity.cpp +2 -0
- esphome/components/datetime/time_entity.h +2 -0
- esphome/components/esp32/__init__.py +20 -4
- esphome/components/esp32_improv/__init__.py +82 -1
- esphome/components/esp32_improv/automation.h +72 -0
- esphome/components/esp32_improv/esp32_improv_component.cpp +13 -5
- esphome/components/esp32_improv/esp32_improv_component.h +15 -0
- esphome/components/ethernet/__init__.py +5 -0
- esphome/components/ethernet/ethernet_component.cpp +13 -0
- esphome/components/ethernet/ethernet_component.h +1 -0
- esphome/components/fan/__init__.py +3 -4
- esphome/components/gp2y1010au0f/__init__.py +0 -0
- esphome/components/gp2y1010au0f/gp2y1010au0f.cpp +67 -0
- esphome/components/gp2y1010au0f/gp2y1010au0f.h +52 -0
- esphome/components/gp2y1010au0f/sensor.py +61 -0
- esphome/components/gpio_expander/__init__.py +0 -0
- esphome/components/gpio_expander/cached_gpio.h +38 -0
- esphome/components/grove_gas_mc_v2/__init__.py +0 -0
- esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.cpp +88 -0
- esphome/components/grove_gas_mc_v2/grove_gas_mc_v2.h +39 -0
- esphome/components/grove_gas_mc_v2/sensor.py +77 -0
- esphome/components/haier/climate.py +4 -3
- esphome/components/haier/haier_base.cpp +63 -8
- esphome/components/haier/haier_base.h +29 -3
- esphome/components/haier/hon_climate.cpp +122 -65
- esphome/components/haier/hon_climate.h +18 -2
- esphome/components/haier/smartair2_climate.cpp +21 -21
- esphome/components/haier/switch/__init__.py +91 -0
- esphome/components/haier/switch/beeper.cpp +14 -0
- esphome/components/haier/switch/beeper.h +18 -0
- esphome/components/haier/switch/display.cpp +14 -0
- esphome/components/haier/switch/display.h +18 -0
- esphome/components/haier/switch/health_mode.cpp +14 -0
- esphome/components/haier/switch/health_mode.h +18 -0
- esphome/components/haier/switch/quiet_mode.cpp +14 -0
- esphome/components/haier/switch/quiet_mode.h +18 -0
- esphome/components/hmac_md5/hmac_md5.cpp +2 -0
- esphome/components/hmac_md5/hmac_md5.h +2 -1
- esphome/components/i2s_audio/speaker/__init__.py +19 -0
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +1 -1
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +2 -0
- esphome/components/ili9xxx/ili9xxx_display.h +1 -0
- esphome/components/image/__init__.py +12 -12
- esphome/components/image/image.cpp +44 -0
- esphome/components/image/image.h +17 -2
- esphome/components/inkplate6/display.py +2 -0
- esphome/components/inkplate6/inkplate.h +30 -2
- esphome/components/light/__init__.py +3 -4
- esphome/components/lock/__init__.py +3 -4
- esphome/components/lvgl/__init__.py +16 -5
- esphome/components/lvgl/defines.py +1 -0
- esphome/components/lvgl/hello_world.py +64 -0
- esphome/components/lvgl/lv_validation.py +159 -3
- esphome/components/lvgl/lvgl_esphome.cpp +0 -43
- esphome/components/lvgl/lvgl_esphome.h +0 -4
- esphome/components/lvgl/styles.py +3 -2
- esphome/components/lvgl/text/__init__.py +3 -3
- esphome/components/lvgl/widgets/__init__.py +2 -0
- esphome/components/lvgl/widgets/animimg.py +3 -4
- esphome/components/lvgl/widgets/dropdown.py +5 -1
- esphome/components/lvgl/widgets/meter.py +16 -11
- esphome/components/md5/__init__.py +6 -0
- esphome/components/md5/md5.cpp +2 -0
- esphome/components/md5/md5.h +2 -0
- esphome/components/micro_wake_word/__init__.py +7 -0
- esphome/components/mics_4514/sensor.py +11 -26
- esphome/components/modbus_controller/__init__.py +7 -5
- esphome/components/modbus_controller/binary_sensor/__init__.py +6 -6
- esphome/components/modbus_controller/number/__init__.py +5 -6
- esphome/components/modbus_controller/output/__init__.py +10 -14
- esphome/components/modbus_controller/select/__init__.py +1 -1
- esphome/components/modbus_controller/sensor/__init__.py +7 -7
- esphome/components/modbus_controller/switch/__init__.py +6 -7
- esphome/components/modbus_controller/text_sensor/__init__.py +8 -9
- esphome/components/mqtt/__init__.py +3 -0
- esphome/components/mqtt/mqtt_client.cpp +2 -0
- esphome/components/mqtt/mqtt_client.h +2 -0
- esphome/components/nau7802/__init__.py +0 -0
- esphome/components/nau7802/nau7802.cpp +323 -0
- esphome/components/nau7802/nau7802.h +121 -0
- esphome/components/nau7802/sensor.py +134 -0
- esphome/components/nextion/base_component.py +1 -0
- esphome/components/nextion/display.py +4 -0
- esphome/components/nextion/nextion.cpp +19 -4
- esphome/components/nextion/nextion.h +16 -0
- esphome/components/npi19/__init__.py +0 -0
- esphome/components/npi19/npi19.cpp +111 -0
- esphome/components/npi19/npi19.h +30 -0
- esphome/components/npi19/sensor.py +52 -0
- esphome/components/number/__init__.py +3 -5
- esphome/components/online_image/__init__.py +1 -1
- esphome/components/online_image/online_image.h +1 -2
- esphome/components/opentherm/__init__.py +57 -0
- esphome/components/opentherm/hub.cpp +277 -0
- esphome/components/opentherm/hub.h +110 -0
- esphome/components/opentherm/opentherm.cpp +568 -0
- esphome/components/opentherm/opentherm.h +347 -0
- esphome/components/pulse_counter/pulse_counter_sensor.cpp +8 -1
- esphome/components/pulse_counter/pulse_counter_sensor.h +1 -0
- esphome/components/radon_eye_ble/radon_eye_listener.cpp +10 -3
- esphome/components/remote_transmitter/__init__.py +18 -2
- esphome/components/remote_transmitter/remote_transmitter.h +6 -0
- esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +2 -0
- esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +2 -0
- esphome/components/remote_transmitter/remote_transmitter_libretiny.cpp +2 -0
- esphome/components/select/__init__.py +3 -4
- esphome/components/sensor/__init__.py +3 -4
- esphome/components/st7701s/st7701s.cpp +21 -8
- esphome/components/st7701s/st7701s.h +2 -0
- esphome/components/switch/__init__.py +3 -4
- esphome/components/tca9555/__init__.py +72 -0
- esphome/components/tca9555/tca9555.cpp +140 -0
- esphome/components/tca9555/tca9555.h +64 -0
- esphome/components/tcs34725/tcs34725.cpp +62 -64
- esphome/components/tem3200/__init__.py +0 -0
- esphome/components/tem3200/sensor.py +55 -0
- esphome/components/tem3200/tem3200.cpp +151 -0
- esphome/components/tem3200/tem3200.h +30 -0
- esphome/components/template/binary_sensor/__init__.py +19 -6
- esphome/components/text/__init__.py +3 -4
- esphome/components/text_sensor/__init__.py +3 -4
- esphome/components/thermostat/climate.py +11 -9
- esphome/components/thermostat/thermostat_climate.cpp +21 -15
- esphome/components/tm1638/binary_sensor/__init__.py +3 -2
- esphome/components/tm1638/display.py +5 -5
- esphome/components/tm1638/output/__init__.py +3 -2
- esphome/components/tm1638/switch/__init__.py +3 -2
- esphome/components/update/__init__.py +3 -4
- esphome/components/valve/__init__.py +3 -4
- esphome/components/web_server/__init__.py +78 -22
- esphome/components/web_server/server_index_v3.h +3989 -3979
- esphome/components/web_server/web_server.cpp +212 -33
- esphome/components/web_server/web_server.h +10 -1
- esphome/components/wifi/wifi_component_esp_idf.cpp +4 -5
- esphome/config_validation.py +1 -0
- esphome/const.py +12 -2
- esphome/core/defines.h +4 -2
- esphome/core/helpers.cpp +46 -10
- esphome/core/helpers.h +8 -0
- esphome/core/ring_buffer.cpp +12 -2
- esphome/core/ring_buffer.h +3 -0
- {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/METADATA +5 -3
- {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/RECORD +188 -139
- {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/LICENSE +0 -0
- {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/WHEEL +0 -0
- {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/entry_points.txt +0 -0
- {esphome-2024.9.2.dist-info → esphome-2024.10.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,347 @@
|
|
1
|
+
/*
|
2
|
+
* OpenTherm protocol implementation. Originally taken from https://github.com/jpraus/arduino-opentherm, but
|
3
|
+
* heavily modified to comply with ESPHome coding standards and provide better logging.
|
4
|
+
* Original code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
|
5
|
+
* Public License, which is compatible with GPLv3 license, which covers C++ part of ESPHome project.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#pragma once
|
9
|
+
|
10
|
+
#include <string>
|
11
|
+
#include <sstream>
|
12
|
+
#include <iomanip>
|
13
|
+
#include "esphome/core/hal.h"
|
14
|
+
#include "esphome/core/log.h"
|
15
|
+
|
16
|
+
#if defined(ESP32) || defined(USE_ESP_IDF)
|
17
|
+
#include "driver/timer.h"
|
18
|
+
#endif
|
19
|
+
|
20
|
+
namespace esphome {
|
21
|
+
namespace opentherm {
|
22
|
+
|
23
|
+
// TODO: Account for immutable semantics change in hub.cpp when doing later installments of OpenTherm PR
|
24
|
+
template<class T> constexpr T read_bit(T value, uint8_t bit) { return (value >> bit) & 0x01; }
|
25
|
+
|
26
|
+
template<class T> constexpr T set_bit(T value, uint8_t bit) { return value |= (1UL << bit); }
|
27
|
+
|
28
|
+
template<class T> constexpr T clear_bit(T value, uint8_t bit) { return value &= ~(1UL << bit); }
|
29
|
+
|
30
|
+
template<class T> constexpr T write_bit(T value, uint8_t bit, uint8_t bit_value) {
|
31
|
+
return bit_value ? setBit(value, bit) : clearBit(value, bit);
|
32
|
+
}
|
33
|
+
|
34
|
+
enum OperationMode {
|
35
|
+
IDLE = 0, // no operation
|
36
|
+
|
37
|
+
LISTEN = 1, // waiting for transmission to start
|
38
|
+
READ = 2, // reading 32-bit data frame
|
39
|
+
RECEIVED = 3, // data frame received with valid start and stop bit
|
40
|
+
|
41
|
+
WRITE = 4, // writing data with timer_
|
42
|
+
SENT = 5, // all data written to output
|
43
|
+
|
44
|
+
ERROR_PROTOCOL = 8, // manchester protocol data transfer error
|
45
|
+
ERROR_TIMEOUT = 9 // read timeout
|
46
|
+
};
|
47
|
+
|
48
|
+
enum ProtocolErrorType {
|
49
|
+
NO_ERROR = 0, // No error
|
50
|
+
NO_TRANSITION = 1, // No transition in the middle of the bit
|
51
|
+
INVALID_STOP_BIT = 2, // Stop bit wasn't present when expected
|
52
|
+
PARITY_ERROR = 3, // Parity check didn't pass
|
53
|
+
NO_CHANGE_TOO_LONG = 4, // No level change for too much timer ticks
|
54
|
+
};
|
55
|
+
|
56
|
+
enum MessageType {
|
57
|
+
READ_DATA = 0,
|
58
|
+
READ_ACK = 4,
|
59
|
+
WRITE_DATA = 1,
|
60
|
+
WRITE_ACK = 5,
|
61
|
+
INVALID_DATA = 2,
|
62
|
+
DATA_INVALID = 6,
|
63
|
+
UNKNOWN_DATAID = 7
|
64
|
+
};
|
65
|
+
|
66
|
+
enum MessageId {
|
67
|
+
STATUS = 0,
|
68
|
+
CH_SETPOINT = 1,
|
69
|
+
CONTROLLER_CONFIG = 2,
|
70
|
+
DEVICE_CONFIG = 3,
|
71
|
+
COMMAND_CODE = 4,
|
72
|
+
FAULT_FLAGS = 5,
|
73
|
+
REMOTE = 6,
|
74
|
+
COOLING_CONTROL = 7,
|
75
|
+
CH2_SETPOINT = 8,
|
76
|
+
CH_SETPOINT_OVERRIDE = 9,
|
77
|
+
TSP_COUNT = 10,
|
78
|
+
TSP_COMMAND = 11,
|
79
|
+
FHB_SIZE = 12,
|
80
|
+
FHB_COMMAND = 13,
|
81
|
+
MAX_MODULATION_LEVEL = 14,
|
82
|
+
MAX_BOILER_CAPACITY = 15, // u8_hb - u8_lb gives min modulation level
|
83
|
+
ROOM_SETPOINT = 16,
|
84
|
+
MODULATION_LEVEL = 17,
|
85
|
+
CH_WATER_PRESSURE = 18,
|
86
|
+
DHW_FLOW_RATE = 19,
|
87
|
+
DAY_TIME = 20,
|
88
|
+
DATE = 21,
|
89
|
+
YEAR = 22,
|
90
|
+
ROOM_SETPOINT_CH2 = 23,
|
91
|
+
ROOM_TEMP = 24,
|
92
|
+
FEED_TEMP = 25,
|
93
|
+
DHW_TEMP = 26,
|
94
|
+
OUTSIDE_TEMP = 27,
|
95
|
+
RETURN_WATER_TEMP = 28,
|
96
|
+
SOLAR_STORE_TEMP = 29,
|
97
|
+
SOLAR_COLLECT_TEMP = 30,
|
98
|
+
FEED_TEMP_CH2 = 31,
|
99
|
+
DHW2_TEMP = 32,
|
100
|
+
EXHAUST_TEMP = 33,
|
101
|
+
FAN_SPEED = 35,
|
102
|
+
FLAME_CURRENT = 36,
|
103
|
+
DHW_BOUNDS = 48,
|
104
|
+
CH_BOUNDS = 49,
|
105
|
+
OTC_CURVE_BOUNDS = 50,
|
106
|
+
DHW_SETPOINT = 56,
|
107
|
+
MAX_CH_SETPOINT = 57,
|
108
|
+
OTC_CURVE_RATIO = 58,
|
109
|
+
|
110
|
+
// HVAC Specific Message IDs
|
111
|
+
HVAC_STATUS = 70,
|
112
|
+
REL_VENT_SETPOINT = 71,
|
113
|
+
DEVICE_VENT = 74,
|
114
|
+
REL_VENTILATION = 77,
|
115
|
+
REL_HUMID_EXHAUST = 78,
|
116
|
+
SUPPLY_INLET_TEMP = 80,
|
117
|
+
SUPPLY_OUTLET_TEMP = 81,
|
118
|
+
EXHAUST_INLET_TEMP = 82,
|
119
|
+
EXHAUST_OUTLET_TEMP = 83,
|
120
|
+
NOM_REL_VENTILATION = 87,
|
121
|
+
|
122
|
+
OVERRIDE_FUNC = 100,
|
123
|
+
OEM_DIAGNOSTIC = 115,
|
124
|
+
BURNER_STARTS = 116,
|
125
|
+
CH_PUMP_STARTS = 117,
|
126
|
+
DHW_PUMP_STARTS = 118,
|
127
|
+
DHW_BURNER_STARTS = 119,
|
128
|
+
BURNER_HOURS = 120,
|
129
|
+
CH_PUMP_HOURS = 121,
|
130
|
+
DHW_PUMP_HOURS = 122,
|
131
|
+
DHW_BURNER_HOURS = 123,
|
132
|
+
OT_VERSION_CONTROLLER = 124,
|
133
|
+
OT_VERSION_DEVICE = 125,
|
134
|
+
VERSION_CONTROLLER = 126,
|
135
|
+
VERSION_DEVICE = 127
|
136
|
+
};
|
137
|
+
|
138
|
+
enum BitPositions { STOP_BIT = 33 };
|
139
|
+
|
140
|
+
/**
|
141
|
+
* Structure to hold Opentherm data packet content.
|
142
|
+
* Use f88(), u16() or s16() functions to get appropriate value of data packet accoridng to id of message.
|
143
|
+
*/
|
144
|
+
struct OpenthermData {
|
145
|
+
uint8_t type;
|
146
|
+
uint8_t id;
|
147
|
+
uint8_t valueHB;
|
148
|
+
uint8_t valueLB;
|
149
|
+
|
150
|
+
OpenthermData() : type(0), id(0), valueHB(0), valueLB(0) {}
|
151
|
+
|
152
|
+
/**
|
153
|
+
* @return float representation of data packet value
|
154
|
+
*/
|
155
|
+
float f88();
|
156
|
+
|
157
|
+
/**
|
158
|
+
* @param float number to set as value of this data packet
|
159
|
+
*/
|
160
|
+
void f88(float value);
|
161
|
+
|
162
|
+
/**
|
163
|
+
* @return unsigned 16b integer representation of data packet value
|
164
|
+
*/
|
165
|
+
uint16_t u16();
|
166
|
+
|
167
|
+
/**
|
168
|
+
* @param unsigned 16b integer number to set as value of this data packet
|
169
|
+
*/
|
170
|
+
void u16(uint16_t value);
|
171
|
+
|
172
|
+
/**
|
173
|
+
* @return signed 16b integer representation of data packet value
|
174
|
+
*/
|
175
|
+
int16_t s16();
|
176
|
+
|
177
|
+
/**
|
178
|
+
* @param signed 16b integer number to set as value of this data packet
|
179
|
+
*/
|
180
|
+
void s16(int16_t value);
|
181
|
+
};
|
182
|
+
|
183
|
+
struct OpenThermError {
|
184
|
+
ProtocolErrorType error_type;
|
185
|
+
uint32_t capture;
|
186
|
+
uint8_t clock;
|
187
|
+
uint32_t data;
|
188
|
+
uint8_t bit_pos;
|
189
|
+
};
|
190
|
+
|
191
|
+
/**
|
192
|
+
* Opentherm static class that supports either listening or sending Opentherm data packets in the same time
|
193
|
+
*/
|
194
|
+
class OpenTherm {
|
195
|
+
public:
|
196
|
+
OpenTherm(InternalGPIOPin *in_pin, InternalGPIOPin *out_pin, int32_t device_timeout = 800);
|
197
|
+
|
198
|
+
/**
|
199
|
+
* Setup pins.
|
200
|
+
*/
|
201
|
+
bool initialize();
|
202
|
+
|
203
|
+
/**
|
204
|
+
* Start listening for Opentherm data packet comming from line connected to given pin.
|
205
|
+
* If data packet is received then has_message() function returns true and data packet can be retrieved by calling
|
206
|
+
* get_message() function. If timeout > 0 then this function waits for incomming data package for timeout millis and
|
207
|
+
* if no data packet is recevived, error state is indicated by is_error() function. If either data packet is received
|
208
|
+
* or timeout is reached listening is stopped.
|
209
|
+
*/
|
210
|
+
void listen();
|
211
|
+
|
212
|
+
/**
|
213
|
+
* Use this function to check whether listen() function already captured a valid data packet.
|
214
|
+
*
|
215
|
+
* @return true if data packet has been captured from line by listen() function.
|
216
|
+
*/
|
217
|
+
bool has_message() { return mode_ == OperationMode::RECEIVED; }
|
218
|
+
|
219
|
+
/**
|
220
|
+
* Use this to retrive data packed captured by listen() function. Data packet is ready when has_message() function
|
221
|
+
* returns true. This function can be called multiple times until stop() is called.
|
222
|
+
*
|
223
|
+
* @param data reference to data structure to which fill the data packet data.
|
224
|
+
* @return true if packet was ready and was filled into data structure passed, false otherwise.
|
225
|
+
*/
|
226
|
+
bool get_message(OpenthermData &data);
|
227
|
+
|
228
|
+
/**
|
229
|
+
* Immediately send out Opentherm data packet to line connected on given pin.
|
230
|
+
* Completed data transfer is indicated by is_sent() function.
|
231
|
+
* Error state is indicated by is_error() function.
|
232
|
+
*
|
233
|
+
* @param data Opentherm data packet.
|
234
|
+
*/
|
235
|
+
void send(OpenthermData &data);
|
236
|
+
|
237
|
+
/**
|
238
|
+
* Stops listening for data packet or sending out data packet and resets internal state of this class.
|
239
|
+
* Stops all timers and unattaches all interrupts.
|
240
|
+
*/
|
241
|
+
void stop();
|
242
|
+
|
243
|
+
/**
|
244
|
+
* Get protocol error details in case a protocol error occured.
|
245
|
+
* @param error reference to data structure to which fill the error details
|
246
|
+
* @return true if protocol error occured during last conversation, false otherwise.
|
247
|
+
*/
|
248
|
+
bool get_protocol_error(OpenThermError &error);
|
249
|
+
|
250
|
+
/**
|
251
|
+
* Use this function to check whether send() function already finished sending data packed to line.
|
252
|
+
*
|
253
|
+
* @return true if data packet has been sent, false otherwise.
|
254
|
+
*/
|
255
|
+
bool is_sent() { return mode_ == OperationMode::SENT; }
|
256
|
+
|
257
|
+
/**
|
258
|
+
* Indicates whether listinig or sending is not in progress.
|
259
|
+
* That also means that no timers are running and no interrupts are attached.
|
260
|
+
*
|
261
|
+
* @return true if listening nor sending is in progress.
|
262
|
+
*/
|
263
|
+
bool is_idle() { return mode_ == OperationMode::IDLE; }
|
264
|
+
|
265
|
+
/**
|
266
|
+
* Indicates whether last listen() or send() operation ends up with an error. Includes both timeout and
|
267
|
+
* protocol errors.
|
268
|
+
*
|
269
|
+
* @return true if last listen() or send() operation ends up with an error.
|
270
|
+
*/
|
271
|
+
bool is_error() { return mode_ == OperationMode::ERROR_TIMEOUT || mode_ == OperationMode::ERROR_PROTOCOL; }
|
272
|
+
|
273
|
+
/**
|
274
|
+
* Indicates whether last listen() or send() operation ends up with a *timeout* error
|
275
|
+
* @return true if last listen() or send() operation ends up with a *timeout* error.
|
276
|
+
*/
|
277
|
+
bool is_timeout() { return mode_ == OperationMode::ERROR_TIMEOUT; }
|
278
|
+
|
279
|
+
/**
|
280
|
+
* Indicates whether last listen() or send() operation ends up with a *protocol* error
|
281
|
+
* @return true if last listen() or send() operation ends up with a *protocol* error.
|
282
|
+
*/
|
283
|
+
bool is_protocol_error() { return mode_ == OperationMode::ERROR_PROTOCOL; }
|
284
|
+
|
285
|
+
bool is_active() { return mode_ == LISTEN || mode_ == READ || mode_ == WRITE; }
|
286
|
+
|
287
|
+
OperationMode get_mode() { return mode_; }
|
288
|
+
|
289
|
+
std::string debug_data(OpenthermData &data);
|
290
|
+
std::string debug_error(OpenThermError &error);
|
291
|
+
|
292
|
+
const char *protocol_error_to_to_str(ProtocolErrorType error_type);
|
293
|
+
const char *message_type_to_str(MessageType message_type);
|
294
|
+
const char *operation_mode_to_str(OperationMode mode);
|
295
|
+
const char *message_id_to_str(MessageId id);
|
296
|
+
|
297
|
+
static bool timer_isr(OpenTherm *arg);
|
298
|
+
|
299
|
+
#ifdef ESP8266
|
300
|
+
static void esp8266_timer_isr();
|
301
|
+
#endif
|
302
|
+
|
303
|
+
private:
|
304
|
+
InternalGPIOPin *in_pin_;
|
305
|
+
InternalGPIOPin *out_pin_;
|
306
|
+
ISRInternalGPIOPin isr_in_pin_;
|
307
|
+
ISRInternalGPIOPin isr_out_pin_;
|
308
|
+
|
309
|
+
#if defined(ESP32) || defined(USE_ESP_IDF)
|
310
|
+
timer_group_t timer_group_;
|
311
|
+
timer_idx_t timer_idx_;
|
312
|
+
#endif
|
313
|
+
|
314
|
+
OperationMode mode_;
|
315
|
+
ProtocolErrorType error_type_;
|
316
|
+
uint32_t capture_;
|
317
|
+
uint8_t clock_;
|
318
|
+
uint32_t data_;
|
319
|
+
uint8_t bit_pos_;
|
320
|
+
int32_t timeout_counter_; // <0 no timeout
|
321
|
+
|
322
|
+
int32_t device_timeout_;
|
323
|
+
|
324
|
+
#if defined(ESP32) || defined(USE_ESP_IDF)
|
325
|
+
bool init_esp32_timer_();
|
326
|
+
void start_esp32_timer_(uint64_t alarm_value);
|
327
|
+
#endif
|
328
|
+
|
329
|
+
void stop_timer_();
|
330
|
+
|
331
|
+
void read_(); // data detected start reading
|
332
|
+
void start_read_timer_(); // reading timer_ to sample at 1/5 of manchester code bit length (at 5kHz)
|
333
|
+
void start_write_timer_(); // writing timer_ to send manchester code (at 2kHz)
|
334
|
+
bool check_parity_(uint32_t val);
|
335
|
+
|
336
|
+
void bit_read_(uint8_t value);
|
337
|
+
ProtocolErrorType verify_stop_bit_(uint8_t value);
|
338
|
+
void write_bit_(uint8_t high, uint8_t clock);
|
339
|
+
|
340
|
+
#ifdef ESP8266
|
341
|
+
// ESP8266 timer can accept callback with no parameters, so we have this hack to save a static instance of OpenTherm
|
342
|
+
static OpenTherm *instance_;
|
343
|
+
#endif
|
344
|
+
};
|
345
|
+
|
346
|
+
} // namespace opentherm
|
347
|
+
} // namespace esphome
|
@@ -53,12 +53,19 @@ pulse_counter_t BasicPulseCounterStorage::read_raw_value() {
|
|
53
53
|
#ifdef HAS_PCNT
|
54
54
|
bool HwPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) {
|
55
55
|
static pcnt_unit_t next_pcnt_unit = PCNT_UNIT_0;
|
56
|
+
static pcnt_channel_t next_pcnt_channel = PCNT_CHANNEL_0;
|
56
57
|
this->pin = pin;
|
57
58
|
this->pin->setup();
|
58
59
|
this->pcnt_unit = next_pcnt_unit;
|
60
|
+
this->pcnt_channel = next_pcnt_channel;
|
59
61
|
next_pcnt_unit = pcnt_unit_t(int(next_pcnt_unit) + 1);
|
62
|
+
if (int(next_pcnt_unit) >= PCNT_UNIT_0 + PCNT_UNIT_MAX) {
|
63
|
+
next_pcnt_unit = PCNT_UNIT_0;
|
64
|
+
next_pcnt_channel = pcnt_channel_t(int(next_pcnt_channel) + 1);
|
65
|
+
}
|
60
66
|
|
61
67
|
ESP_LOGCONFIG(TAG, " PCNT Unit Number: %u", this->pcnt_unit);
|
68
|
+
ESP_LOGCONFIG(TAG, " PCNT Channel Number: %u", this->pcnt_channel);
|
62
69
|
|
63
70
|
pcnt_count_mode_t rising = PCNT_COUNT_DIS, falling = PCNT_COUNT_DIS;
|
64
71
|
switch (this->rising_edge_mode) {
|
@@ -94,7 +101,7 @@ bool HwPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) {
|
|
94
101
|
.counter_h_lim = 0,
|
95
102
|
.counter_l_lim = 0,
|
96
103
|
.unit = this->pcnt_unit,
|
97
|
-
.channel =
|
104
|
+
.channel = this->pcnt_channel,
|
98
105
|
};
|
99
106
|
esp_err_t error = pcnt_unit_config(&pcnt_config);
|
100
107
|
if (error != ESP_OK) {
|
@@ -1,5 +1,7 @@
|
|
1
1
|
#include "radon_eye_listener.h"
|
2
2
|
#include "esphome/core/log.h"
|
3
|
+
#include <algorithm>
|
4
|
+
#include <vector>
|
3
5
|
|
4
6
|
#ifdef USE_ESP32
|
5
7
|
|
@@ -10,9 +12,14 @@ static const char *const TAG = "radon_eye_ble";
|
|
10
12
|
|
11
13
|
bool RadonEyeListener::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
|
12
14
|
if (not device.get_name().empty()) {
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
// Vector containing the prefixes to search for
|
16
|
+
std::vector<std::string> prefixes = {"FR:R", "FR:I", "FR:H"};
|
17
|
+
|
18
|
+
// Check if the device name starts with any of the prefixes
|
19
|
+
if (std::any_of(prefixes.begin(), prefixes.end(),
|
20
|
+
[&](const std::string &prefix) { return device.get_name().rfind(prefix, 0) == 0; })) {
|
21
|
+
// Device found
|
22
|
+
ESP_LOGD(TAG, "Found Radon Eye device Name: %s (MAC: %s)", device.get_name().c_str(),
|
16
23
|
device.address_str().c_str());
|
17
24
|
}
|
18
25
|
}
|
@@ -1,10 +1,14 @@
|
|
1
|
+
from esphome import automation, pins
|
1
2
|
import esphome.codegen as cg
|
3
|
+
from esphome.components import esp32_rmt, remote_base
|
2
4
|
import esphome.config_validation as cv
|
3
|
-
from esphome import pins
|
4
|
-
from esphome.components import remote_base, esp32_rmt
|
5
5
|
from esphome.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN, CONF_RMT_CHANNEL
|
6
6
|
|
7
7
|
AUTO_LOAD = ["remote_base"]
|
8
|
+
|
9
|
+
CONF_ON_TRANSMIT = "on_transmit"
|
10
|
+
CONF_ON_COMPLETE = "on_complete"
|
11
|
+
|
8
12
|
remote_transmitter_ns = cg.esphome_ns.namespace("remote_transmitter")
|
9
13
|
RemoteTransmitterComponent = remote_transmitter_ns.class_(
|
10
14
|
"RemoteTransmitterComponent", remote_base.RemoteTransmitterBase, cg.Component
|
@@ -19,6 +23,8 @@ CONFIG_SCHEMA = cv.Schema(
|
|
19
23
|
cv.percentage_int, cv.Range(min=1, max=100)
|
20
24
|
),
|
21
25
|
cv.Optional(CONF_RMT_CHANNEL): esp32_rmt.validate_rmt_channel(tx=True),
|
26
|
+
cv.Optional(CONF_ON_TRANSMIT): automation.validate_automation(single=True),
|
27
|
+
cv.Optional(CONF_ON_COMPLETE): automation.validate_automation(single=True),
|
22
28
|
}
|
23
29
|
).extend(cv.COMPONENT_SCHEMA)
|
24
30
|
|
@@ -32,3 +38,13 @@ async def to_code(config):
|
|
32
38
|
await cg.register_component(var, config)
|
33
39
|
|
34
40
|
cg.add(var.set_carrier_duty_percent(config[CONF_CARRIER_DUTY_PERCENT]))
|
41
|
+
|
42
|
+
if on_transmit_config := config.get(CONF_ON_TRANSMIT):
|
43
|
+
await automation.build_automation(
|
44
|
+
var.get_transmit_trigger(), [], on_transmit_config
|
45
|
+
)
|
46
|
+
|
47
|
+
if on_complete_config := config.get(CONF_ON_COMPLETE):
|
48
|
+
await automation.build_automation(
|
49
|
+
var.get_complete_trigger(), [], on_complete_config
|
50
|
+
)
|
@@ -33,6 +33,9 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase,
|
|
33
33
|
|
34
34
|
void set_carrier_duty_percent(uint8_t carrier_duty_percent) { this->carrier_duty_percent_ = carrier_duty_percent; }
|
35
35
|
|
36
|
+
Trigger<> *get_transmit_trigger() const { return this->transmit_trigger_; };
|
37
|
+
Trigger<> *get_complete_trigger() const { return this->complete_trigger_; };
|
38
|
+
|
36
39
|
protected:
|
37
40
|
void send_internal(uint32_t send_times, uint32_t send_wait) override;
|
38
41
|
#if defined(USE_ESP8266) || defined(USE_LIBRETINY)
|
@@ -57,6 +60,9 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase,
|
|
57
60
|
bool inverted_{false};
|
58
61
|
#endif
|
59
62
|
uint8_t carrier_duty_percent_;
|
63
|
+
|
64
|
+
Trigger<> *transmit_trigger_{new Trigger<>()};
|
65
|
+
Trigger<> *complete_trigger_{new Trigger<>()};
|
60
66
|
};
|
61
67
|
|
62
68
|
} // namespace remote_transmitter
|
@@ -124,6 +124,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
|
124
124
|
ESP_LOGE(TAG, "Empty data");
|
125
125
|
return;
|
126
126
|
}
|
127
|
+
this->transmit_trigger_->trigger();
|
127
128
|
for (uint32_t i = 0; i < send_times; i++) {
|
128
129
|
esp_err_t error = rmt_write_items(this->channel_, this->rmt_temp_.data(), this->rmt_temp_.size(), true);
|
129
130
|
if (error != ESP_OK) {
|
@@ -135,6 +136,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
|
135
136
|
if (i + 1 < send_times)
|
136
137
|
delayMicroseconds(send_wait);
|
137
138
|
}
|
139
|
+
this->complete_trigger_->trigger();
|
138
140
|
}
|
139
141
|
|
140
142
|
} // namespace remote_transmitter
|
@@ -76,6 +76,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
|
76
76
|
uint32_t on_time, off_time;
|
77
77
|
this->calculate_on_off_time_(this->temp_.get_carrier_frequency(), &on_time, &off_time);
|
78
78
|
this->target_time_ = 0;
|
79
|
+
this->transmit_trigger_->trigger();
|
79
80
|
for (uint32_t i = 0; i < send_times; i++) {
|
80
81
|
for (int32_t item : this->temp_.get_data()) {
|
81
82
|
if (item > 0) {
|
@@ -93,6 +94,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
|
93
94
|
if (i + 1 < send_times)
|
94
95
|
this->target_time_ += send_wait;
|
95
96
|
}
|
97
|
+
this->complete_trigger_->trigger();
|
96
98
|
}
|
97
99
|
|
98
100
|
} // namespace remote_transmitter
|
@@ -78,6 +78,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
|
78
78
|
uint32_t on_time, off_time;
|
79
79
|
this->calculate_on_off_time_(this->temp_.get_carrier_frequency(), &on_time, &off_time);
|
80
80
|
this->target_time_ = 0;
|
81
|
+
this->transmit_trigger_->trigger();
|
81
82
|
for (uint32_t i = 0; i < send_times; i++) {
|
82
83
|
InterruptLock lock;
|
83
84
|
for (int32_t item : this->temp_.get_data()) {
|
@@ -96,6 +97,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
|
96
97
|
if (i + 1 < send_times)
|
97
98
|
this->target_time_ += send_wait;
|
98
99
|
}
|
100
|
+
this->complete_trigger_->trigger();
|
99
101
|
}
|
100
102
|
|
101
103
|
} // namespace remote_transmitter
|
@@ -14,7 +14,7 @@ from esphome.const import (
|
|
14
14
|
CONF_OPERATION,
|
15
15
|
CONF_OPTION,
|
16
16
|
CONF_TRIGGER_ID,
|
17
|
-
|
17
|
+
CONF_WEB_SERVER,
|
18
18
|
)
|
19
19
|
from esphome.core import CORE, coroutine_with_priority
|
20
20
|
from esphome.cpp_generator import MockObjClass
|
@@ -104,9 +104,8 @@ async def setup_select_core_(var, config, *, options: list[str]):
|
|
104
104
|
mqtt_ = cg.new_Pvariable(mqtt_id, var)
|
105
105
|
await mqtt.register_mqtt_component(mqtt_, config)
|
106
106
|
|
107
|
-
if
|
108
|
-
|
109
|
-
web_server.add_entity_to_sorting_list(web_server_, var, config)
|
107
|
+
if web_server_config := config.get(CONF_WEB_SERVER):
|
108
|
+
await web_server.add_entity_config(var, web_server_config)
|
110
109
|
|
111
110
|
|
112
111
|
async def register_select(var, config, *, options: list[str]):
|
@@ -36,7 +36,7 @@ from esphome.const import (
|
|
36
36
|
CONF_TYPE,
|
37
37
|
CONF_UNIT_OF_MEASUREMENT,
|
38
38
|
CONF_VALUE,
|
39
|
-
|
39
|
+
CONF_WEB_SERVER,
|
40
40
|
CONF_WINDOW_SIZE,
|
41
41
|
DEVICE_CLASS_APPARENT_POWER,
|
42
42
|
DEVICE_CLASS_AQI,
|
@@ -800,9 +800,8 @@ async def setup_sensor_core_(var, config):
|
|
800
800
|
else:
|
801
801
|
cg.add(mqtt_.set_expire_after(expire_after))
|
802
802
|
|
803
|
-
if
|
804
|
-
|
805
|
-
web_server.add_entity_to_sorting_list(web_server_, var, config)
|
803
|
+
if web_server_config := config.get(CONF_WEB_SERVER):
|
804
|
+
await web_server.add_entity_config(var, web_server_config)
|
806
805
|
|
807
806
|
|
808
807
|
async def register_sensor(var, config):
|
@@ -8,8 +8,14 @@ namespace st7701s {
|
|
8
8
|
void ST7701S::setup() {
|
9
9
|
esph_log_config(TAG, "Setting up ST7701S");
|
10
10
|
this->spi_setup();
|
11
|
+
this->write_init_sequence_();
|
12
|
+
|
11
13
|
esp_lcd_rgb_panel_config_t config{};
|
12
14
|
config.flags.fb_in_psram = 1;
|
15
|
+
#if ESP_IDF_VERSION_MAJOR >= 5
|
16
|
+
config.bounce_buffer_size_px = this->width_ * 10;
|
17
|
+
config.num_fbs = 1;
|
18
|
+
#endif // ESP_IDF_VERSION_MAJOR
|
13
19
|
config.timings.h_res = this->width_;
|
14
20
|
config.timings.v_res = this->height_;
|
15
21
|
config.timings.hsync_pulse_width = this->hsync_pulse_width_;
|
@@ -21,7 +27,6 @@ void ST7701S::setup() {
|
|
21
27
|
config.timings.flags.pclk_active_neg = this->pclk_inverted_;
|
22
28
|
config.timings.pclk_hz = this->pclk_frequency_;
|
23
29
|
config.clk_src = LCD_CLK_SRC_PLL160M;
|
24
|
-
config.sram_trans_align = 64;
|
25
30
|
config.psram_trans_align = 64;
|
26
31
|
size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]);
|
27
32
|
for (size_t i = 0; i != data_pin_count; i++) {
|
@@ -34,15 +39,21 @@ void ST7701S::setup() {
|
|
34
39
|
config.de_gpio_num = this->de_pin_->get_pin();
|
35
40
|
config.pclk_gpio_num = this->pclk_pin_->get_pin();
|
36
41
|
esp_err_t err = esp_lcd_new_rgb_panel(&config, &this->handle_);
|
42
|
+
ESP_ERROR_CHECK(esp_lcd_panel_reset(this->handle_));
|
43
|
+
ESP_ERROR_CHECK(esp_lcd_panel_init(this->handle_));
|
37
44
|
if (err != ESP_OK) {
|
38
45
|
esph_log_e(TAG, "lcd_new_rgb_panel failed: %s", esp_err_to_name(err));
|
39
46
|
}
|
40
|
-
ESP_ERROR_CHECK(esp_lcd_panel_reset(this->handle_));
|
41
|
-
ESP_ERROR_CHECK(esp_lcd_panel_init(this->handle_));
|
42
|
-
this->write_init_sequence_();
|
43
47
|
esph_log_config(TAG, "ST7701S setup complete");
|
44
48
|
}
|
45
49
|
|
50
|
+
void ST7701S::loop() {
|
51
|
+
#if ESP_IDF_VERSION_MAJOR >= 5
|
52
|
+
if (this->handle_ != nullptr)
|
53
|
+
esp_lcd_rgb_panel_restart(this->handle_);
|
54
|
+
#endif // ESP_IDF_VERSION_MAJOR
|
55
|
+
}
|
56
|
+
|
46
57
|
void ST7701S::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order,
|
47
58
|
display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) {
|
48
59
|
if (w <= 0 || h <= 0)
|
@@ -160,10 +171,12 @@ void ST7701S::write_init_sequence_() {
|
|
160
171
|
this->write_data_(val);
|
161
172
|
ESP_LOGD(TAG, "write MADCTL %X", val);
|
162
173
|
this->write_command_(this->invert_colors_ ? INVERT_ON : INVERT_OFF);
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
174
|
+
// can't avoid this inline delay due to the need to complete setup before anything else tries to draw.
|
175
|
+
delay(120); // NOLINT
|
176
|
+
this->write_command_(SLEEP_OUT);
|
177
|
+
this->write_command_(DISPLAY_ON);
|
178
|
+
this->spi_teardown(); // SPI not needed after this
|
179
|
+
delay(10);
|
167
180
|
}
|
168
181
|
|
169
182
|
void ST7701S::dump_config() {
|
@@ -33,6 +33,8 @@ class ST7701S : public display::Display,
|
|
33
33
|
public:
|
34
34
|
void update() override { this->do_update_(); }
|
35
35
|
void setup() override;
|
36
|
+
void complete_setup_();
|
37
|
+
void loop() override;
|
36
38
|
void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order,
|
37
39
|
display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) override;
|
38
40
|
|
@@ -14,7 +14,7 @@ from esphome.const import (
|
|
14
14
|
CONF_ON_TURN_ON,
|
15
15
|
CONF_RESTORE_MODE,
|
16
16
|
CONF_TRIGGER_ID,
|
17
|
-
|
17
|
+
CONF_WEB_SERVER,
|
18
18
|
DEVICE_CLASS_EMPTY,
|
19
19
|
DEVICE_CLASS_OUTLET,
|
20
20
|
DEVICE_CLASS_SWITCH,
|
@@ -156,9 +156,8 @@ async def setup_switch_core_(var, config):
|
|
156
156
|
mqtt_ = cg.new_Pvariable(mqtt_id, var)
|
157
157
|
await mqtt.register_mqtt_component(mqtt_, config)
|
158
158
|
|
159
|
-
if
|
160
|
-
|
161
|
-
web_server.add_entity_to_sorting_list(web_server_, var, config)
|
159
|
+
if web_server_config := config.get(CONF_WEB_SERVER):
|
160
|
+
await web_server.add_entity_config(var, web_server_config)
|
162
161
|
|
163
162
|
if (device_class := config.get(CONF_DEVICE_CLASS)) is not None:
|
164
163
|
cg.add(var.set_device_class(device_class))
|