Compare commits

...
Author SHA1 Message Date
J. Nick Koston 9bc9fc1b9b Reuse the platform SubEntities for gate numbers and share the door command check
Gate thresholds go through numbers.create instead of a SubEntities per gate,
the hoermann_hcp buttons pass the hub id, and the one-shot door command tests
share one check.
2026-10-16 13:43:11 -10:00
J. Nick Koston 90cf7abbde Merge branch 'apply-entities' into apply-entities-migrate 2026-10-16 13:42:28 -10:00
J. Nick Koston b8a0de91db [core] Simplify the Apply entity helpers
Fold the function cache into SubEntities, make each domain's APPLY_ENTITY public,
shorten the class and docstring comments and reuse the shared test hub.
2026-10-16 13:42:23 -10:00
J. Nick Koston fb54defeda [ld2410] Warn when a threshold number matches no gate 2026-10-16 13:06:31 -10:00
J. Nick Koston e2d37f0d7e Merge branch 'apply-entities' into apply-entities-migrate 2026-10-16 12:20:54 -10:00
J. Nick Koston 2937d81216 Mark the test recorders as intentional mutable globals 2026-10-16 12:20:50 -10:00
J. Nick Koston 9d59415766 [hoermann_hcp] Move the door command tests next to the hub tests 2026-10-16 11:47:43 -10:00
J. Nick Koston 29ef01a207 Merge branch 'apply-entities' into apply-entities-migrate 2026-10-16 11:45:51 -10:00
J. Nick Koston 05a4b256db Reject an unknown publish= value 2026-10-16 11:45:47 -10:00
J. Nick Koston e8e98ee3db [ld2410] Find the gate from the number so all gate numbers share one class 2026-10-16 11:05:25 -10:00
J. Nick Koston 6aa647638c Merge branch 'apply-entities' into apply-entities-migrate 2026-10-16 11:04:41 -10:00
J. Nick Koston d0427c36eb [core] Share the apply function naming with automations and check the Apply class at codegen 2026-10-16 11:04:36 -10:00
J. Nick Koston e2c2fdfb3d [bq25186] Use Apply entities for the SHIP_RST buttons 2026-10-16 10:51:36 -10:00
J. Nick Koston 7425b8d3b1 [es8388] Use Apply entities for the line selects 2026-10-16 10:51:36 -10:00
J. Nick Koston 5f697bb0d6 [espectre] Use Apply entities for the recalibrate button and traffic select 2026-10-16 10:51:36 -10:00
J. Nick Koston 8f79467d5f [at581x] Use an Apply entity for the RF switch 2026-10-16 10:51:36 -10:00
J. Nick Koston 5ca927da8e [hoermann_hcp] Use Apply entities for the buttons 2026-10-16 10:48:32 -10:00
J. Nick Koston 776a7f68d8 [tfluna] Use Apply entities for the buttons 2026-10-16 10:48:31 -10:00
J. Nick Koston 87de7d679e [haier] Use Apply entities for the cleaning buttons and airflow selects 2026-10-16 10:48:31 -10:00
J. Nick Koston e75a10ec7d [seeed_mr24hpc1] Use Apply entities for the forwarding buttons, switch, numbers and selects 2026-10-16 10:48:31 -10:00
J. Nick Koston f0ea8edfad [seeed_mr60fda2] Use Apply entities for the forwarding buttons and selects 2026-10-16 10:48:31 -10:00
J. Nick Koston 5df5d44516 [ld2420] Use Apply entities for the forwarding buttons and select 2026-10-16 10:48:31 -10:00
J. Nick Koston dd59a827ff [ld2450] Use Apply entities for the forwarding buttons, switches, numbers and selects 2026-10-16 10:48:30 -10:00
J. Nick Koston ed9b566091 [ld2412] Use Apply entities for the forwarding buttons, switches, numbers and selects 2026-10-16 10:48:30 -10:00
J. Nick Koston 5fd7c33916 [ld2410] Use Apply entities for the forwarding buttons, switches, numbers and selects 2026-10-16 10:48:30 -10:00
J. Nick Koston a990231342 [core] Add Apply button, switch, number and select entities for hub forwarders 2026-10-16 10:48:29 -10:00
Igor StadnykandJ. Nick Koston 10d3ced897 [core] Parse unit values as one decimal so listed floats match, fixing at581x power consumption (#20889)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-16 10:11:56 -10:00
Bascht74 6fa7b87e6a [lp5562] Add the current per channel and logarithmic dimming (#20903) 2026-10-16 10:04:45 -10:00
c0b7c5e590 [dfrobot_sen0395] Forward trigger arguments in settings actions (#20885)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-16 10:03:07 -10:00
dependabot[bot] 57dd09018e Bump yamlrocks from 0.6.1 to 0.7.0 (#20904)
Signed-off-by: dependabot[bot] <support@github.com>
2026-10-16 10:00:58 -10:00
Clyde Stubbs 04aa59563d [display] Drop the color order from draw_pixels_at() and ColorUtil (#20884) 2026-10-17 06:45:03 +11:00
9440012413 [mics_5524] Add MiCS-5524 gas sensor platform (1/2) (#19721)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-16 09:14:06 -10:00
Bascht74 38db8c1554 [ci] Fail a hung integration test instead of waiting for the job limit (#20902) 2026-10-16 09:00:55 -10:00
ab0c32c2aa [haier_water_heater] Initial water-heater implementation tested with Haier VH3W (#20765)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-16 08:50:13 -10:00
cd6a34401b [web_server] Do not match internal entities by URL unless include_internal is set (#20883)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-16 08:22:46 -10:00
Igor StadnykandJ. Nick Koston 5ab92ed363 [ld2450] Handle footer bytes in zone query responses (#20852)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-16 08:15:17 -10:00
1368ce4342 [dfrobot_sen0609] Add restart, factory reset and query buttons (#20877)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-16 17:31:58 +00:00
Remco van Essen dc0d79635b [ld2410][ld2412] Move CONF_QUERY_PARAMS to the shared constants (#20878) 2026-10-16 07:12:49 -10:00
J. Nick Koston 1ff6b29b0d [components] Let core report communication failures in dump_config (4/5) (#20873) 2026-10-16 08:41:52 -04:00
J. Nick Koston 49caeae780 [components] Let core report communication failures in dump_config (3/5) (#20872) 2026-10-16 08:40:54 -04:00
J. Nick Koston e1a6c615b1 [core] Document passing the failure reason to mark_failed in AGENTS.md (#20879) 2026-10-16 08:40:06 -04:00
J. Nick Koston e95e56f100 [components] Let core report communication failures in dump_config (2/5) (#20871) 2026-10-16 08:39:20 -04:00
J. Nick Koston 126dc8b0b2 [components] Let core report communication failures in dump_config (1/5) (#20870) 2026-10-16 08:38:55 -04:00
esphome[bot] 3298988f5d Bump bundled esphome-device-builder to 1.24.0 (#20851)
Co-authored-by: esphome[bot] <115708604+esphome[bot]@users.noreply.github.com>
2026-10-15 23:11:26 -10:00
802c2633ed [image] Draw rows in the outer loop and hand opaque RGB565 and RGB blocks to the display (#20653)
Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 18:38:58 +11:00
51b1fdcc8b [i2s_audio] Add full duplex support (#19959)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: J. Nick Koston <nick@koston.org>
2026-10-15 21:35:46 -10:00
6555da2906 [display] Fall back per pixel when a bulk blit does not match the panel (#20652)
Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 16:57:11 +11:00
J. Nick Koston 6dbd15b903 [pca9505] Validate interrupt_pin with the shared expander validator (#20853) 2026-10-15 15:02:26 -10:00
Jonathan Swoboda 0399379c0d [lp5562] Pin the test fixture to the shared I2C bus (#20856) 2026-10-16 00:56:40 +00:00
462 changed files with 6904 additions and 3975 deletions

No files matched your search

+4 -1
View File
@@ -395,6 +395,8 @@ jobs:
- common
- determine-jobs
if: needs.determine-jobs.outputs.integration-tests == 'true'
# A hung test is failed by pytest's --timeout below; this bounds the rest
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
@@ -471,7 +473,8 @@ jobs:
exit 1
fi
echo "Bucket ${{ matrix.bucket.name }}: running ${#test_files[@]} integration tests"
pytest -vv --no-cov --tb=native --durations=30 -n auto --dist worksteal \
# A hung test fails after 30 min: the 15 min shared build lock wait plus a cold compile
pytest -vv --no-cov --tb=native --durations=30 -n auto --dist worksteal --timeout=1800 \
--junitxml=junit-integration.xml "${test_files[@]}"
- name: Upload test artifacts
# Tests that compare rendered output write the image they actually got here, so a
+9
View File
@@ -225,6 +225,15 @@ file does, and it is the authority when they disagree. The most useful starting
stays inside the `#ifdef`.
* **Failures after `setup()`:** `mark_failed()` is for `setup()` only. A runtime read or write failure
sets `status_set_warning()` and the next success clears it; writes skip work when `is_failed()`.
* **`dump_config()` already prints the failure reason:** for a failed component, core prints
`<component> is marked FAILED: <reason>` right after the component's `dump_config()`, using the reason
passed to `mark_failed()`. So `dump_config()` never checks `is_failed()` to log a failure, and no
`error_code_` member exists only to pick that message. Pass the reason where setup fails instead:
`this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL))` for a failed bus transfer, a short specific reason
otherwise (`LOG_STR("Wrong chip ID")`). Core also logs it at that moment, so no `ESP_LOGE` repeats it
before `mark_failed()`; keep a separate line only when it prints a value read at run time, such as the
chip ID that did not match. Only the first reason is kept, so do not call `status_set_error()` before
`mark_failed()` and do not mark the component failed again after a helper already did.
* **Fixed platform facts compile to nothing:** gate on `#ifdef USE_ESP8266` and friends, not on a
runtime check of something the build already knows.
* **Logging string literals:** wrap literals passed as `%s` arguments in `LOG_STR_LITERAL()` so they
+2
View File
@@ -252,6 +252,7 @@ esphome/components/haier/text_sensor/* @paveldn
esphome/components/haier_tundra/* @fauxpark
esphome/components/haier_tundra/button/* @fauxpark
esphome/components/haier_tundra/switch/* @fauxpark
esphome/components/haier_water_heater/* @TheLexus
esphome/components/havells_solar/* @sourabhjaiswal
esphome/components/hbridge/fan/* @WeekendWarrior
esphome/components/hbridge/light/* @DotNetDann
@@ -390,6 +391,7 @@ esphome/components/micro_wake_word/* @jesserockz @kahrendt
esphome/components/micronova/* @edenhaus @jorre05
esphome/components/microphone/* @jesserockz @kahrendt
esphome/components/mics_4514/* @jesserockz
esphome/components/mics_5524/* @nliaudat
esphome/components/midea/* @dudanov
esphome/components/midea_ir/* @dudanov
esphome/components/midea_portasplit/* @Fexiven
+1 -1
View File
@@ -22,7 +22,7 @@ RUN \
-r /requirements.txt
# Install the ESPHome Device Builder dashboard.
RUN uv pip install --no-cache-dir esphome-device-builder==1.23.1
RUN uv pip install --no-cache-dir esphome-device-builder==1.24.0
RUN \
platformio settings set enable_telemetry No \
+11 -3
View File
@@ -426,12 +426,20 @@ def _apply_function(
) -> MockObj:
"""Emit the generated function and declare ``id_`` as the ``ApplyAction`` or
``ApplyCondition`` templated on it, so ``play()`` calls it directly."""
fn = cg.static_function(
f"esphome__{id_.id}__fn", return_type, lambda_args, statements
)
fn = apply_static_function(id_, return_type, lambda_args, statements)
return cg.new_Pvariable(id_, cg.TemplateArguments(fn, *template_arg))
def apply_static_function(
id_: ID,
return_type: SafeExpType,
params: TemplateArgsType,
statements: list[str],
) -> MockObj:
"""Emit the static function generated for ``id_`` and return an expression naming it."""
return cg.static_function(f"esphome__{id_.id}__fn", return_type, params, statements)
async def _render_values(
name: str,
target: str,
+2 -5
View File
@@ -11,7 +11,7 @@ static const uint8_t ADS1115_REGISTER_CONFIG = 0x01;
void ADS1115Component::setup() {
uint16_t value;
if (!this->read_byte_16(ADS1115_REGISTER_CONVERSION, &value)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
@@ -58,7 +58,7 @@ void ADS1115Component::setup() {
config |= 0b0000000000000011;
if (!this->write_byte_16(ADS1115_REGISTER_CONFIG, config)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
this->prev_config_ = config;
@@ -66,9 +66,6 @@ void ADS1115Component::setup() {
void ADS1115Component::dump_config() {
ESP_LOGCONFIG(TAG, "ADS1115:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
}
float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1115Gain gain,
ADS1115Resolution resolution, ADS1115Samplerate samplerate) {
+4 -11
View File
@@ -52,8 +52,7 @@ void AHT10Component::setup() {
break;
}
if (error_code != i2c::ERROR_OK) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
uint8_t cal_attempts = 0;
@@ -61,20 +60,17 @@ void AHT10Component::setup() {
while (data & AHT10_STATUS_BUSY) {
delay(AHT10_DEFAULT_DELAY);
if (this->read(&data, 1) != i2c::ERROR_OK) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
++cal_attempts;
if (cal_attempts > AHT10_INIT_ATTEMPTS) {
ESP_LOGE(TAG, "Initialization timed out");
this->mark_failed();
this->mark_failed(LOG_STR("Initialization timed out"));
return;
}
}
if ((data & 0x68) != 0x08) { // Bit[6:5] = 0b00, NORMAL mode and Bit[3] = 0b1, CALIBRATED
ESP_LOGE(TAG, "Initialization failed");
this->mark_failed();
this->mark_failed(LOG_STR("Initialization failed"));
return;
}
}
@@ -152,9 +148,6 @@ void AHT10Component::update() {
void AHT10Component::dump_config() {
ESP_LOGCONFIG(TAG, "AHT10:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
}
+1 -6
View File
@@ -10,8 +10,7 @@ ESPHOME_LOG_TAG(TAG, "aic3204");
#define ERROR_CHECK(err, msg) \
if (!(err)) { \
ESP_LOGE(TAG, msg); \
this->mark_failed(); \
this->mark_failed(LOG_STR(msg)); \
return; \
}
@@ -108,10 +107,6 @@ void AIC3204::setup() {
void AIC3204::dump_config() {
ESP_LOGCONFIG(TAG, "AIC3204:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
}
bool AIC3204::set_mute_off() {
+6 -22
View File
@@ -42,21 +42,18 @@ bool AM2315C::reset_register_(uint8_t reg) {
data[2] = 0;
ESP_LOGD(TAG, "Reset register: 0x%02x", reg);
if (this->write(data, 3) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Write failed!");
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return false;
}
delay(5);
if (this->read(data, 3) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Read failed!");
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return false;
}
delay(10);
data[0] = 0xB0 | reg;
if (this->write(data, 3) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Write failed!");
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return false;
}
delay(5);
@@ -76,8 +73,7 @@ void AM2315C::setup() {
// get status
uint8_t status = 0;
if (this->read(&status, 1) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Read failed!");
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
@@ -86,18 +82,9 @@ void AM2315C::setup() {
// never required during testing
if ((status & 0x18) != 0x18) {
ESP_LOGD(TAG, "Resetting AM2315C registers");
if (!this->reset_register_(0x1B)) {
this->mark_failed();
// reset_register_() marks the component failed with its own reason
if (!this->reset_register_(0x1B) || !this->reset_register_(0x1C) || !this->reset_register_(0x1E))
return;
}
if (!this->reset_register_(0x1C)) {
this->mark_failed();
return;
}
if (!this->reset_register_(0x1E)) {
this->mark_failed();
return;
}
}
}
@@ -168,9 +155,6 @@ void AM2315C::update() {
void AM2315C::dump_config() {
ESP_LOGCONFIG(TAG, "AM2315C:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
}
+1 -4
View File
@@ -37,16 +37,13 @@ void AM2320Component::setup() {
data[0] = 0;
data[1] = 4;
if (!this->read_data_(data)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
}
void AM2320Component::dump_config() {
ESP_LOGD(TAG, "AM2320:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
}
+2 -2
View File
@@ -5,8 +5,8 @@
namespace esphome::animation {
Animation::Animation(const uint8_t *data_start, int width, int height, uint32_t animation_frame_count,
image::ImageType type, image::Transparency transparent)
: Image(data_start, width, height, type, transparent),
image::ImageType type, image::Transparency transparent, bool big_endian)
: Image(data_start, width, height, type, transparent, big_endian),
animation_data_start_(data_start),
current_frame_(0),
animation_frame_count_(animation_frame_count),
+1 -1
View File
@@ -6,7 +6,7 @@ namespace esphome::animation {
class Animation final : public image::Image {
public:
Animation(const uint8_t *data_start, int width, int height, uint32_t animation_frame_count, image::ImageType type,
image::Transparency transparent);
image::Transparency transparent, bool big_endian = false);
uint32_t get_animation_frame_count() const;
int get_current_frame() const;
+2 -1
View File
@@ -1,6 +1,6 @@
from esphome import automation
import esphome.codegen as cg
from esphome.components.const import CONF_LOOP
from esphome.components.const import CONF_BYTE_ORDER, CONF_LOOP
from esphome.components.file import image as file_image
from esphome.components.file.image import image_schema, write_image
from esphome.components.image import Image_, validate_settings
@@ -90,6 +90,7 @@ async def setup_animation(config: ConfigType) -> None:
frame_count,
image_type,
trans_value,
config.get(CONF_BYTE_ORDER) == "BIG_ENDIAN",
)
if loop_config := config.get(CONF_LOOP):
start = loop_config[CONF_START_FRAME]
+4 -21
View File
@@ -34,8 +34,7 @@ enum { // APDS9306 registers
#define APDS9306_ERROR_CHECK(func, error) \
if (!(func)) { \
ESP_LOGE(TAG, error); \
this->mark_failed(); \
this->mark_failed(LOG_STR(error)); \
return; \
}
#define APDS9306_WARNING_CHECK(func, warning) \
@@ -48,21 +47,19 @@ enum { // APDS9306 registers
ESP_LOGV(TAG, "Writing 0x%02x to 0x%02x", value, reg); \
if (!this->write_byte(reg, value)) { \
ESP_LOGE(TAG, "Failed writing 0x%02x to 0x%02x", value, reg); \
this->mark_failed(); \
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL)); \
return; \
}
void APDS9306::setup() {
uint8_t id;
if (!this->read_byte(APDS9306_PART_ID, &id)) { // Part ID register
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (id != 0xB1 && id != 0xB3) { // 0xB1 for APDS9306 0xB3 for APDS9306-065
this->error_code_ = WRONG_ID;
this->mark_failed();
this->mark_failed(LOG_STR("APDS9306 has invalid id"));
return;
}
@@ -89,20 +86,6 @@ void APDS9306::dump_config() {
LOG_SENSOR("", "APDS9306", this);
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
switch (this->error_code_) {
case COMMUNICATION_FAILED:
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
break;
case WRONG_ID:
ESP_LOGE(TAG, "APDS9306 has invalid id!");
break;
default:
ESP_LOGE(TAG, "Setting up APDS9306 registers failed!");
break;
}
}
ESP_LOGCONFIG(TAG,
" Gain: %u\n"
" Measurement rate: %u\n"
-6
View File
@@ -50,12 +50,6 @@ class APDS9306 final : public sensor::Sensor, public PollingComponent, public i2
void set_ambient_light_gain(AmbientLightGain gain) { this->gain_ = gain; }
protected:
enum ErrorCode {
NONE = 0,
COMMUNICATION_FAILED,
WRONG_ID,
} error_code_{NONE};
MeasurementBitWidth bit_width_;
MeasurementRate measurement_rate_;
AmbientLightGain gain_;
+3 -19
View File
@@ -8,7 +8,7 @@ ESPHOME_LOG_TAG(TAG, "apds9960");
#define APDS9960_ERROR_CHECK(func) \
if (!(func)) { \
this->mark_failed(); \
this->mark_failed(LOG_STR("Setting up APDS9960 registers failed")); \
return; \
}
#define APDS9960_WRITE_BYTE(reg, value) APDS9960_ERROR_CHECK(this->write_byte(reg, value));
@@ -16,14 +16,12 @@ ESPHOME_LOG_TAG(TAG, "apds9960");
void APDS9960::setup() {
uint8_t id;
if (!this->read_byte(0x92, &id)) { // ID register
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (id != 0xAB && id != 0x9C && id != 0xA8 && id != 0x9E) { // APDS9960 all should have one of these IDs
this->error_code_ = WRONG_ID;
this->mark_failed();
this->mark_failed(LOG_STR("APDS9960 has invalid id"));
return;
}
@@ -135,20 +133,6 @@ void APDS9960::dump_config() {
LOG_SENSOR(" ", "Clear channel", this->clear_sensor_);
LOG_SENSOR(" ", "Proximity", this->proximity_sensor_);
#endif
if (this->is_failed()) {
switch (this->error_code_) {
case COMMUNICATION_FAILED:
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
break;
case WRONG_ID:
ESP_LOGE(TAG, "APDS9960 has invalid id!");
break;
default:
ESP_LOGE(TAG, "Setting up APDS9960 registers failed!");
break;
}
}
}
#define APDS9960_WARNING_CHECK(func, warning) \
-5
View File
@@ -58,11 +58,6 @@ class APDS9960 final : public PollingComponent, public i2c::I2CDevice {
uint8_t gesture_gain_;
uint8_t gesture_wait_time_;
enum ErrorCode {
NONE = 0,
COMMUNICATION_FAILED,
WRONG_ID,
} error_code_{NONE};
bool gesture_up_started_{false};
bool gesture_down_started_{false};
bool gesture_left_started_{false};
+3 -5
View File
@@ -23,7 +23,7 @@ static const uint8_t REGISTER_MAGNITUDE = 0x1B; // 16 bytes / R
void AS5600Component::setup() {
if (!this->read_byte(REGISTER_STATUS).has_value()) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
@@ -54,7 +54,7 @@ void AS5600Component::setup() {
// write config to config register
if (!this->write_byte_16(REGISTER_CONF, config)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
@@ -87,10 +87,8 @@ void AS5600Component::dump_config() {
ESP_LOGCONFIG(TAG, "AS5600:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
if (this->is_failed())
return;
}
ESP_LOGCONFIG(TAG,
" Watchdog: %d\n"
+2 -6
View File
@@ -14,14 +14,13 @@ void AS7341Component::setup() {
this->read_byte(AS7341_ID, &id);
ESP_LOGCONFIG(TAG, " Read ID: 0x%X", id);
if ((id & 0xFC) != (AS7341_CHIP_ID << 2)) {
this->mark_failed();
this->mark_failed(LOG_STR("Wrong chip ID"));
return;
}
// Power on (enter IDLE state)
if (!this->enable_power(true)) {
ESP_LOGE(TAG, " Power on failed!");
this->mark_failed();
this->mark_failed(LOG_STR("Power on failed"));
return;
}
@@ -35,9 +34,6 @@ void AS7341Component::setup() {
void AS7341Component::dump_config() {
ESP_LOGCONFIG(TAG, "AS7341:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
LOG_UPDATE_INTERVAL(this);
ESP_LOGCONFIG(TAG,
" Gain: %u\n"
-3
View File
@@ -355,9 +355,6 @@ void AS734XComponent::dump_config() {
#ifdef USE_AS734X_RGB
LOG_TEXT_SENSOR(" ", "RGB hex", this->rgb_hex_sensor_);
#endif
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
}
void AS734XComponent::enable_led(bool enable) {
+1 -1
View File
@@ -93,7 +93,7 @@ def _megahertz(value: float) -> int:
def _microamps(value: float) -> int:
return int(value * 1000000)
return round(value * 1000000)
RADAR_SETTINGS_SCHEMA = cv.Schema(
+6 -7
View File
@@ -4,14 +4,13 @@ import esphome.config_validation as cv
from esphome.const import DEVICE_CLASS_SWITCH, ICON_WIFI
from esphome.types import ConfigType
from .. import CONF_AT581X_ID, AT581XComponent, at581x_ns
from .. import CONF_AT581X_ID, AT581XComponent
DEPENDENCIES = ["at581x"]
RFSwitch = at581x_ns.class_("RFSwitch", switch.Switch)
CONFIG_SCHEMA = switch.switch_schema(
RFSwitch,
switch.ApplySwitch,
device_class=DEVICE_CLASS_SWITCH,
icon=ICON_WIFI,
).extend(
@@ -24,7 +23,7 @@ CONFIG_SCHEMA = switch.switch_schema(
async def to_code(config: ConfigType) -> None:
at581x_component = await cg.get_variable(config[CONF_AT581X_ID])
s = await switch.new_switch(config)
await cg.register_parented(s, config[CONF_AT581X_ID])
cg.add(at581x_component.set_rf_power_switch(s))
hub = await cg.get_variable(config[CONF_AT581X_ID])
await switch.sub_switches(config, parent=hub).create(
config, hub.set_rf_power_switch, apply="set_rf_mode(state)", publish="before"
)
@@ -1,10 +0,0 @@
#include "rf_switch.h"
namespace esphome::at581x {
void RFSwitch::write_state(bool state) {
this->publish_state(state);
this->parent_->set_rf_mode(state);
}
} // namespace esphome::at581x
@@ -1,13 +0,0 @@
#pragma once
#include "esphome/components/switch/switch.h"
#include "../at581x.h"
namespace esphome::at581x {
class RFSwitch final : public switch_::Switch, public Parented<AT581XComponent> {
protected:
void write_state(bool state) override;
};
} // namespace esphome::at581x
+3 -6
View File
@@ -52,7 +52,7 @@ void ATM90E26Component::setup() {
uint16_t read = this->read16_(ATM90E26_REGISTER_LASTDATA);
if (read != 0x0030) {
ESP_LOGW(TAG, "Could not initialize ATM90E26 IC, check SPI settings: %d", read);
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
// TODO: 100 * <nominal voltage, e.g. 230> * sqrt(2) * <fraction of nominal, e.g. 0.9> / (4 * gain_voltage/32768)
@@ -120,21 +120,18 @@ void ATM90E26Component::setup() {
ESP_LOGW(TAG, "Could not initialize ATM90E26 IC: CS1 was incorrect, expected: 0x%04X",
this->read16_(ATM90E26_REGISTER_CS1));
this->mark_failed();
this->mark_failed(LOG_STR("Checksum mismatch"));
}
if (sys_status & 0x3000) { // Checksum 2 Error
ESP_LOGW(TAG, "Could not initialize ATM90E26 IC: CS2 was incorrect, expected: 0x%04X",
this->read16_(ATM90E26_REGISTER_CS2));
this->mark_failed();
this->mark_failed(LOG_STR("Checksum mismatch"));
}
}
void ATM90E26Component::dump_config() {
ESP_LOGCONFIG("", "ATM90E26:");
LOG_PIN(" CS Pin: ", this->cs_);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
LOG_UPDATE_INTERVAL(this);
LOG_SENSOR(" ", "Voltage A", this->voltage_sensor_);
LOG_SENSOR(" ", "Current A", this->current_sensor_);
+1 -4
View File
@@ -168,7 +168,7 @@ void ATM90E32Component::setup() {
this->write16_(ATM90E32_REGISTER_CFGREGACCEN, 0x55AA); // enable register config access
if (!this->validate_spi_read_(0x55AA, "setup()")) {
ESP_LOGW(TAG, "Could not initialize ATM90E32 IC, check SPI settings");
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
@@ -411,9 +411,6 @@ void ATM90E32Component::log_calibration_status_() {
void ATM90E32Component::dump_config() {
ESP_LOGCONFIG("", "ATM90E32:");
LOG_PIN(" CS Pin: ", this->cs_);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
LOG_UPDATE_INTERVAL(this);
LOG_SENSOR(" ", "Voltage A", this->phase_[PHASEA].voltage_sensor_);
LOG_SENSOR(" ", "Current A", this->phase_[PHASEA].current_sensor_);
+1 -4
View File
@@ -65,7 +65,7 @@ MTreg:
void BH1750Sensor::setup() {
uint8_t turn_on = BH1750_COMMAND_POWER_ON;
if (this->write(&turn_on, 1) != i2c::ERROR_OK) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
this->state_ = IDLE;
@@ -74,9 +74,6 @@ void BH1750Sensor::setup() {
void BH1750Sensor::dump_config() {
LOG_SENSOR("", "BH1750", this);
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL_FOR, this->get_name().c_str());
}
LOG_UPDATE_INTERVAL(this);
}
@@ -62,7 +62,8 @@ void BluedroidGattClient::loop() {
auto ret = esp_ble_gattc_app_register(this->app_id);
if (ret) {
ESP_LOGE(TAG, "gattc app register failed: app_id=%d code=%d", this->app_id, ret);
this->mark_failed();
this->mark_failed(
LOG_STR("Registration failed; if the error was ESP_GATT_NO_RESOURCES, reduce the connection slots"));
}
// Do not wait for REG_EVT; connect() rejects until it lands.
this->set_idle_();
@@ -108,12 +109,7 @@ void BluedroidGattClient::ble_before_disabled_event_handler() {
this->enable_loop();
}
void BluedroidGattClient::dump_config() {
ESP_LOGCONFIG(TAG, "Bluedroid GATT client %d", this->connection_index_);
if (this->is_failed()) {
ESP_LOGE(TAG, " Registration failed; if the error was ESP_GATT_NO_RESOURCES, reduce the connection slots");
}
}
void BluedroidGattClient::dump_config() { ESP_LOGCONFIG(TAG, "Bluedroid GATT client %d", this->connection_index_); }
// ---- contract ops ----
@@ -680,7 +676,8 @@ bool BluedroidGattClient::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
this->gattc_if_ = esp_gattc_if;
} else {
ESP_LOGE(TAG, "[%d] gattc app registration failed, status=%d", this->connection_index_, param->reg.status);
this->mark_failed();
this->mark_failed(
LOG_STR("Registration failed; if the error was ESP_GATT_NO_RESOURCES, reduce the connection slots"));
}
break;
}
@@ -76,16 +76,14 @@ void RP2GattClient::setup() {
// Pre-create every pool entry so the packet handlers' allocate() calls are
// always a free-list pop -- the IRQ path must never reach malloc().
if (!this->event_pool_.warm() || !this->notify_pool_.warm()) {
ESP_LOGE(TAG, "GATT event pool warm-up failed");
this->mark_failed();
this->mark_failed(LOG_STR("GATT event pool warm-up failed"));
return;
}
// Register this engine for IRQ-context event routing.
if (instance_count >= ESPHOME_BLE_GATT_CLIENT_COUNT) {
// Cannot happen with codegen-sized storage; refuse loudly if it ever does.
ESP_LOGE(TAG, "GATT client registry full");
this->mark_failed();
this->mark_failed(LOG_STR("GATT client registry full"));
return;
}
{
+1 -4
View File
@@ -21,7 +21,7 @@ static constexpr uint32_t MAX_TIMER_DURATION_S = 255 * 60;
void BM8563::setup() {
if (!this->write_byte_16(CONTROL_STATUS_1_REG, 0)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
}
@@ -31,9 +31,6 @@ void BM8563::update() { this->read_time(); }
void BM8563::dump_config() {
ESP_LOGCONFIG(TAG, "BM8563:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
}
void BM8563::start_timer(uint32_t duration_s) {
+1 -16
View File
@@ -7,8 +7,6 @@
#include <esphome/components/sensor/sensor.h>
#include <esphome/core/component.h>
#define BME280_ERROR_WRONG_CHIP_ID "Wrong chip ID or no response"
namespace esphome::bme280_base {
ESPHOME_LOG_TAG(TAG, "bme280.sensor");
@@ -100,13 +98,11 @@ void BME280Component::setup() {
}
if (!this->read_byte(BME280_REGISTER_CHIPID, &chip_id)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (chip_id != 0x60) {
this->error_code_ = WRONG_CHIP_ID;
this->mark_failed(LOG_STR(BME280_ERROR_WRONG_CHIP_ID));
this->mark_failed(LOG_STR("Wrong chip ID or no response"));
return;
}
@@ -182,17 +178,6 @@ void BME280Component::setup() {
}
void BME280Component::dump_config() {
ESP_LOGCONFIG(TAG, "BME280:");
switch (this->error_code_) {
case COMMUNICATION_FAILED:
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
break;
case WRONG_CHIP_ID:
ESP_LOGE(TAG, BME280_ERROR_WRONG_CHIP_ID);
break;
case NONE:
default:
break;
}
ESP_LOGCONFIG(TAG, " IIR Filter: %s", iir_filter_to_str(this->iir_filter_));
LOG_UPDATE_INTERVAL(this);
@@ -101,11 +101,6 @@ class BME280Component : public PollingComponent {
sensor::Sensor *temperature_sensor_{nullptr};
sensor::Sensor *pressure_sensor_{nullptr};
sensor::Sensor *humidity_sensor_{nullptr};
enum ErrorCode {
NONE = 0,
COMMUNICATION_FAILED,
WRONG_CHIP_ID,
} error_code_{NONE};
};
} // namespace esphome::bme280_base
+22 -35
View File
@@ -72,22 +72,24 @@ constexpr float BME680_GAS_LOOKUP_TABLE_2[16] PROGMEM = {0.0, 0.0, 0.0, 0.0, 0.
}
void BME680Component::setup() {
if (!this->setup_registers_())
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
}
bool BME680Component::setup_registers_() {
uint8_t chip_id;
if (!this->read_byte(BME680_REGISTER_CHIPID, &chip_id) || chip_id != 0x61) {
this->mark_failed();
return;
return false;
}
// Read calibration
uint8_t coeff1[25];
if (!this->read_bytes(BME680_REGISTER_COEFF1, coeff1, 25)) {
this->mark_failed();
return;
return false;
}
uint8_t coeff2[16];
if (!this->read_bytes(BME680_REGISTER_COEFF2, coeff2, 16)) {
this->mark_failed();
return;
return false;
}
this->calibration_.t1 = coeff2[9] << 8 | coeff2[8];
@@ -119,20 +121,17 @@ void BME680Component::setup() {
uint8_t temp_var = 0;
if (!this->read_byte(0x02, &temp_var)) {
this->mark_failed();
return;
return false;
}
this->calibration_.res_heat_range = ((temp_var & 0x30) / 16);
if (!this->read_byte(0x00, &temp_var)) {
this->mark_failed();
return;
return false;
}
this->calibration_.res_heat_val = (int8_t) temp_var;
if (!this->read_byte(0x04, &temp_var)) {
this->mark_failed();
return;
return false;
}
this->calibration_.range_sw_err = ((int8_t) temp_var & (int8_t) 0xf0) / 16;
@@ -141,41 +140,35 @@ void BME680Component::setup() {
// Config register
uint8_t config_register;
if (!this->read_byte(BME680_REGISTER_CONFIG, &config_register)) {
this->mark_failed();
return;
return false;
}
config_register &= ~0b00011100;
config_register |= (this->iir_filter_ & 0b111) << 2;
if (!this->write_byte(BME680_REGISTER_CONFIG, config_register)) {
this->mark_failed();
return;
return false;
}
// Humidity control register
uint8_t hum_control;
if (!this->read_byte(BME680_REGISTER_CONTROL_HUMIDITY, &hum_control)) {
this->mark_failed();
return;
return false;
}
hum_control &= ~0b00000111;
hum_control |= this->humidity_oversampling_ & 0b111;
if (!this->write_byte(BME680_REGISTER_CONTROL_HUMIDITY, hum_control)) {
this->mark_failed();
return;
return false;
}
// Gas 1 control register
uint8_t gas1_control;
if (!this->read_byte(BME680_REGISTER_CONTROL_GAS1, &gas1_control)) {
this->mark_failed();
return;
return false;
}
gas1_control &= ~0b00011111;
gas1_control |= 1 << 4;
gas1_control |= 0; // profile 0
if (!this->write_byte(BME680_REGISTER_CONTROL_GAS1, gas1_control)) {
this->mark_failed();
return;
return false;
}
const bool heat_off = this->heater_temperature_ == 0 || this->heater_duration_ == 0;
@@ -183,40 +176,34 @@ void BME680Component::setup() {
// Gas 0 control register
uint8_t gas0_control;
if (!this->read_byte(BME680_REGISTER_CONTROL_GAS0, &gas0_control)) {
this->mark_failed();
return;
return false;
}
gas0_control &= ~0b00001000;
gas0_control |= heat_off << 3;
if (!this->write_byte(BME680_REGISTER_CONTROL_GAS0, gas0_control)) {
this->mark_failed();
return;
return false;
}
if (!heat_off) {
// Gas Heater Temperature
uint8_t temperature = this->calc_heater_resistance_(this->heater_temperature_);
if (!this->write_byte(BME680_REGISTER_HEATER_HEAT0, temperature)) {
this->mark_failed();
return;
return false;
}
// Gas Heater Duration
uint8_t duration = this->calc_heater_duration_(this->heater_duration_);
if (!this->write_byte(BME680_REGISTER_HEATER_WAIT0, duration)) {
this->mark_failed();
return;
return false;
}
}
return true;
}
void BME680Component::dump_config() {
ESP_LOGCONFIG(TAG, "BME680:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
ESP_LOGCONFIG(TAG, " IIR Filter: %s", iir_filter_to_str(this->iir_filter_));
LOG_UPDATE_INTERVAL(this);
+2
View File
@@ -101,6 +101,8 @@ class BME680Component final : public PollingComponent, public i2c::I2CDevice {
void update() override;
protected:
/// Configure the sensor registers; false on an I2C failure.
bool setup_registers_();
/// Calculate the heater resistance value to send to the BME680 register.
uint8_t calc_heater_resistance_(uint16_t temperature);
/// Calculate the heater duration value to send to the BME680 register.
+13 -17
View File
@@ -117,18 +117,21 @@ const uint8_t BMI160_REGISTER_DATA_TEMP_MSB = 0x21;
const float GRAVITY_EARTH = 9.80665f;
void BMI160Component::internal_setup_(int stage) {
if (!this->setup_stage_(stage))
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
}
bool BMI160Component::setup_stage_(int stage) {
switch (stage) {
case 0:
uint8_t chipid;
if (!this->read_byte(BMI160_REGISTER_CHIPID, &chipid) || (chipid != 0b11010001)) {
this->mark_failed();
return;
return false;
}
ESP_LOGV(TAG, " Bringing accelerometer out of sleep");
if (!this->write_byte(BMI160_REGISTER_CMD, (uint8_t) Cmd::ACCL_SET_PMU_MODE | (uint8_t) AcclPmuMode::NORMAL)) {
this->mark_failed();
return;
return false;
}
ESP_LOGV(TAG, " Waiting for accelerometer to wake up");
// need to wait (max delay in datasheet) because we can't send commands while another is in progress
@@ -139,8 +142,7 @@ void BMI160Component::internal_setup_(int stage) {
case 1:
ESP_LOGV(TAG, " Bringing gyroscope out of sleep");
if (!this->write_byte(BMI160_REGISTER_CMD, (uint8_t) Cmd::GYRO_SET_PMU_MODE | (uint8_t) GyroPmuMode::NORMAL)) {
this->mark_failed();
return;
return false;
}
ESP_LOGV(TAG, " Waiting for gyroscope to wake up");
// wait between 51 & 81ms, doing 100 to be safe
@@ -152,15 +154,13 @@ void BMI160Component::internal_setup_(int stage) {
uint8_t gyro_config = (uint8_t) GyroBandwidth::OSR4 | (uint8_t) GyroOuputDataRate::HZ_25;
ESP_LOGV(TAG, " Output gyro_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(gyro_config));
if (!this->write_byte(BMI160_REGISTER_GYRO_CONFIG, gyro_config)) {
this->mark_failed();
return;
return false;
}
ESP_LOGV(TAG, " Setting up Gyro Range");
uint8_t gyro_range = (uint8_t) GyroRange::RANGE_2000_DPS;
ESP_LOGV(TAG, " Output gyro_range: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(gyro_range));
if (!this->write_byte(BMI160_REGISTER_GYRO_RANGE, gyro_range)) {
this->mark_failed();
return;
return false;
}
ESP_LOGV(TAG, " Setting up Accel Config");
@@ -168,28 +168,24 @@ void BMI160Component::internal_setup_(int stage) {
(uint8_t) AcclFilterMode::PERF | (uint8_t) AcclBandwidth::RES_AVG16 | (uint8_t) AccelOutputDataRate::HZ_25;
ESP_LOGV(TAG, " Output accel_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(accel_config));
if (!this->write_byte(BMI160_REGISTER_ACCEL_CONFIG, accel_config)) {
this->mark_failed();
return;
return false;
}
ESP_LOGV(TAG, " Setting up Accel Range");
uint8_t accel_range = (uint8_t) AccelRange::RANGE_16G;
ESP_LOGV(TAG, " Output accel_range: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(accel_range));
if (!this->write_byte(BMI160_REGISTER_ACCEL_RANGE, accel_range)) {
this->mark_failed();
return;
return false;
}
this->setup_complete_ = true;
}
return true;
}
void BMI160Component::setup() { this->internal_setup_(0); }
void BMI160Component::dump_config() {
ESP_LOGCONFIG(TAG, "BMI160:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
LOG_UPDATE_INTERVAL(this);
LOG_SENSOR(" ", "Acceleration X", this->accel_x_sensor_);
LOG_SENSOR(" ", "Acceleration Y", this->accel_y_sensor_);
+2
View File
@@ -31,6 +31,8 @@ class BMI160Component final : public PollingComponent, public i2c::I2CDevice {
sensor::Sensor *gyro_z_sensor_{nullptr};
void internal_setup_(int stage);
/// Run one setup stage; false on an I2C failure.
bool setup_stage_(int stage);
bool setup_complete_{false};
/** reads `len` 16-bit little-endian integers from the given i2c register */
+11 -15
View File
@@ -80,28 +80,26 @@ void BMI270Component::setup() {
// 1. Verify chip ID
uint8_t chip_id = 0;
if (!this->read_byte(BMI270_REG_CHIP_ID, &chip_id)) {
ESP_LOGE(TAG, "Failed to read chip ID – check wiring / address");
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (chip_id != BMI270_CHIP_ID_VALUE) {
ESP_LOGE(TAG, "Wrong chip ID: 0x%02X (expected 0x%02X)", chip_id, BMI270_CHIP_ID_VALUE);
this->mark_failed();
this->mark_failed(LOG_STR("Wrong chip ID"));
return;
}
ESP_LOGD(TAG, "Chip ID: 0x%02X", chip_id);
// 2. Soft-reset via CMD register (0x7E = 0xB6)
if (!this->write_byte(BMI270_REG_CMD, BMI270_CMD_SOFT_RESET)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
delay(20);
// 4. Upload the configuration blob
if (!load_config_file_()) {
ESP_LOGE(TAG, "Config file upload failed");
this->mark_failed();
this->mark_failed(LOG_STR("Config file upload failed"));
return;
}
ESP_LOGD(TAG, "Config blob uploaded ✓");
@@ -111,11 +109,11 @@ void BMI270Component::setup() {
uint8_t acc_conf =
(uint8_t) (accel_odr_) | (BMI270_CONF_BWP_NORMAL << BMI270_CONF_BWP_SHIFT) | BMI270_ACC_CONF_PERF_MODE;
if (!this->write_byte(BMI270_REG_ACC_CONF, acc_conf)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (!this->write_byte(BMI270_REG_ACC_RANGE, (uint8_t) accel_range_)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
@@ -124,18 +122,18 @@ void BMI270Component::setup() {
uint8_t gyr_conf = (uint8_t) (gyro_odr_) | (BMI270_CONF_BWP_NORMAL << BMI270_CONF_BWP_SHIFT) |
BMI270_GYR_CONF_NOISE_PERF | BMI270_GYR_CONF_FILTER_PERF;
if (!this->write_byte(BMI270_REG_GYR_CONF, gyr_conf)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (!this->write_byte(BMI270_REG_GYR_RANGE, (uint8_t) gyro_range_)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
// 7. Enable accelerometer, gyroscope, and temperature sensor
// PWR_CTRL bits: temp_en[3] | gyr_en[2] | acc_en[1]
if (!this->write_byte(BMI270_REG_PWR_CTRL, BMI270_PWR_CTRL_IMU)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
delay(5);
@@ -143,7 +141,7 @@ void BMI270Component::setup() {
// 8. Re-enable advanced power save (optional; keeps current low between reads)
// Disabled here for simplicity – leave in performance mode
if (!this->write_byte(BMI270_REG_PWR_CONF, BMI270_PWR_CONF_FIFO_SELF_WAKEUP)) { // bit1 = fifo_self_wakeup
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
@@ -272,10 +270,8 @@ bool BMI270Component::setup_magnetometer_() {
void BMI270Component::dump_config() {
ESP_LOGCONFIG(TAG, "BMI270 IMU:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, " Communication failed!");
if (this->is_failed())
return;
}
ESP_LOGCONFIG(TAG, " Accel range : %s",
LOG_STR_ARG(AccelRangeStrings::get_log_str(this->accel_range_, AccelRangeStrings::LAST_INDEX)));
+1 -4
View File
@@ -24,7 +24,7 @@ void BMP085Component::update() {
void BMP085Component::setup() {
uint8_t data[22];
if (!this->read_bytes(BMP085_REGISTER_AC1_H, data, 22)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
@@ -44,9 +44,6 @@ void BMP085Component::setup() {
void BMP085Component::dump_config() {
ESP_LOGCONFIG(TAG, "BMP085:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, "Connection with BMP085 failed!");
}
LOG_UPDATE_INTERVAL(this);
LOG_SENSOR(" ", "Temperature", this->temperature_);
+1 -17
View File
@@ -2,8 +2,6 @@
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
#define BMP280_ERROR_WRONG_CHIP_ID "Wrong chip ID or no response"
namespace esphome::bmp280_base {
ESPHOME_LOG_TAG(TAG, "bmp280.sensor");
@@ -65,18 +63,15 @@ void BMP280Component::setup() {
// Read the chip id twice, to work around a bug where the first read is 0.
// https://community.st.com/t5/stm32-mcus-products/issue-with-reading-bmp280-chip-id-using-spi/td-p/691855
if (!this->bmp_read_byte(0xD0, &chip_id)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (!this->bmp_read_byte(0xD0, &chip_id)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (chip_id != 0x58) {
this->error_code_ = WRONG_CHIP_ID;
this->mark_failed(LOG_STR(BMP280_ERROR_WRONG_CHIP_ID));
this->mark_failed(LOG_STR("Wrong chip ID or no response"));
return;
}
@@ -130,17 +125,6 @@ void BMP280Component::setup() {
}
void BMP280Component::dump_config() {
ESP_LOGCONFIG(TAG, "BMP280:");
switch (this->error_code_) {
case COMMUNICATION_FAILED:
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
break;
case WRONG_CHIP_ID:
ESP_LOGE(TAG, BMP280_ERROR_WRONG_CHIP_ID);
break;
case NONE:
default:
break;
}
ESP_LOGCONFIG(TAG, " IIR Filter: %s", iir_filter_to_str(this->iir_filter_));
LOG_UPDATE_INTERVAL(this);
@@ -85,11 +85,6 @@ class BMP280Component : public PollingComponent {
BMP280IIRFilter iir_filter_{BMP280_IIR_FILTER_OFF};
sensor::Sensor *temperature_sensor_{nullptr};
sensor::Sensor *pressure_sensor_{nullptr};
enum ErrorCode {
NONE = 0,
COMMUNICATION_FAILED,
WRONG_CHIP_ID,
} error_code_{NONE};
};
} // namespace esphome::bmp280_base
+8 -38
View File
@@ -43,35 +43,27 @@ static const LogString *iir_filter_to_str(IIRFilter filter) {
}
void BMP3XXComponent::setup() {
this->error_code_ = NONE;
// Call the Device base class "initialise" function
if (!reset()) {
ESP_LOGE(TAG, "Failed to reset");
this->error_code_ = ERROR_SENSOR_RESET;
this->mark_failed();
this->mark_failed(LOG_STR("Failed to reset"));
return;
}
if (!read_byte(BMP388_CHIP_ID, &this->chip_id_.reg)) {
ESP_LOGE(TAG, "Can't read chip id");
this->error_code_ = ERROR_COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
ESP_LOGCONFIG(TAG, "Chip %s Id 0x%X", LOG_STR_ARG(chip_type_to_str(this->chip_id_.reg)), this->chip_id_.reg);
if (chip_id_.reg != BMP388_ID && chip_id_.reg != BMP390_ID) {
ESP_LOGE(TAG, "Unknown chip id - is this really a BMP388 or BMP390?");
this->error_code_ = ERROR_WRONG_CHIP_ID;
this->mark_failed();
this->mark_failed(LOG_STR("Wrong chip ID - please check if you are really using a BMP 388 or BMP 390"));
return;
}
// set sensor in sleep mode
stop_conversion();
// Read the calibration parameters into the params structure
if (!read_bytes(BMP388_TRIM_PARAMS, (uint8_t *) &compensation_params_, sizeof(compensation_params_))) {
ESP_LOGE(TAG, "Can't read calibration data");
this->error_code_ = ERROR_COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR("Can't read calibration data"));
return;
}
compensation_float_params_.param_T1 =
@@ -92,9 +84,7 @@ void BMP3XXComponent::setup() {
// Initialise the BMP388 IIR filter register
if (!set_iir_filter(this->iir_filter_)) {
ESP_LOGE(TAG, "Failed to set IIR filter");
this->error_code_ = ERROR_COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR("Failed to set IIR filter"));
return;
}
@@ -113,9 +103,7 @@ void BMP3XXComponent::setup() {
}
// Initialise the BMP388 oversampling register
if (!set_oversampling_register(this->pressure_oversampling_, this->temperature_oversampling_)) {
ESP_LOGE(TAG, "Failed to set oversampling register");
this->error_code_ = ERROR_COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR("Failed to set oversampling register"));
return;
}
}
@@ -125,23 +113,6 @@ void BMP3XXComponent::dump_config() {
"BMP3XX:\n"
" Type: %s (0x%X)",
LOG_STR_ARG(chip_type_to_str(this->chip_id_.reg)), this->chip_id_.reg);
switch (this->error_code_) {
case NONE:
break;
case ERROR_COMMUNICATION_FAILED:
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
break;
case ERROR_WRONG_CHIP_ID:
ESP_LOGE(TAG, "Wrong chip ID (reported id: 0x%X) - please check if you are really using a BMP 388 or BMP 390",
this->chip_id_.reg);
break;
case ERROR_SENSOR_RESET:
ESP_LOGE(TAG, "Failed to reset");
break;
default:
ESP_LOGE(TAG, "Error code %d", (int) this->error_code_);
break;
}
ESP_LOGCONFIG(TAG, " IIR Filter: %s", LOG_STR_ARG(iir_filter_to_str(this->iir_filter_)));
LOG_UPDATE_INTERVAL(this);
if (this->temperature_sensor_) {
@@ -165,8 +136,7 @@ void BMP3XXComponent::update() {
meas_time += 2.02f * oversampling_to_time(this->pressure_oversampling_) + 0.392f;
meas_time += 0.234f;
if (!set_mode(FORCED_MODE)) {
ESP_LOGE(TAG, "Failed start forced mode");
this->mark_failed();
this->mark_failed(LOG_STR("Failed start forced mode"));
return;
}
@@ -124,13 +124,6 @@ class BMP3XXComponent : public PollingComponent {
OperationMode operation_mode_{FORCED_MODE};
sensor::Sensor *temperature_sensor_{nullptr};
sensor::Sensor *pressure_sensor_{nullptr};
enum ErrorCode {
NONE = 0,
ERROR_COMMUNICATION_FAILED,
ERROR_WRONG_CHIP_ID,
ERROR_SENSOR_STATUS,
ERROR_SENSOR_RESET,
} error_code_{NONE};
struct { // The BMP388 compensation trim parameters (coefficients)
uint16_t param_T1;
+10 -64
View File
@@ -38,29 +38,6 @@ static const LogString *iir_filter_to_str(IIRFilter filter) {
void BMP581Component::dump_config() {
ESP_LOGCONFIG(TAG, "BMP581:");
switch (this->error_code_) {
case NONE:
break;
case ERROR_COMMUNICATION_FAILED:
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
break;
case ERROR_WRONG_CHIP_ID:
ESP_LOGE(TAG, "Unknown chip ID");
break;
case ERROR_SENSOR_RESET:
ESP_LOGE(TAG, "Reset failed");
break;
case ERROR_SENSOR_STATUS:
ESP_LOGE(TAG, "Get status failed");
break;
case ERROR_PRIME_IIR_FAILED:
ESP_LOGE(TAG, "IIR Filter failed to prime with initial measurement");
break;
default:
ESP_LOGE(TAG, "Error %d", (int) this->error_code_);
break;
}
LOG_UPDATE_INTERVAL(this);
ESP_LOGCONFIG(TAG, " Measurement conversion time: %ums", this->conversion_time_);
@@ -96,17 +73,13 @@ void BMP581Component::setup() {
* 6) Configure and prime IIR Filter(s), if enabled
*/
this->error_code_ = NONE;
////////////////////
// 1) Soft reboot //
////////////////////
// Power-On-Reboot bit is asserted if sensor successfully reset
if (!this->reset_()) {
ESP_LOGE(TAG, "Reset failed");
this->error_code_ = ERROR_SENSOR_RESET;
this->mark_failed();
this->mark_failed(LOG_STR("Reset failed"));
return;
}
@@ -119,20 +92,14 @@ void BMP581Component::setup() {
// read chip id from sensor
if (!this->bmp_read_byte(BMP581_CHIP_ID, &chip_id)) {
ESP_LOGE(TAG, "Read chip ID failed");
this->error_code_ = ERROR_COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR("Read chip ID failed"));
return;
}
// verify id
if (chip_id != BMP581_ASIC_ID && chip_id != BMP585_ASIC_ID) {
ESP_LOGE(TAG, "Unknown chip ID");
this->error_code_ = ERROR_WRONG_CHIP_ID;
this->mark_failed();
this->mark_failed(LOG_STR("Unknown chip ID"));
return;
}
@@ -142,30 +109,21 @@ void BMP581Component::setup() {
////////////////////////////////////////////////////
if (!this->bmp_read_byte(BMP581_STATUS, &this->status_.reg)) {
ESP_LOGE(TAG, "Failed to read status register");
this->error_code_ = ERROR_COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR("Failed to read status register"));
return;
}
// verify status_nvm_rdy bit (it is asserted if boot was successful)
if (!(this->status_.bit.status_nvm_rdy)) {
ESP_LOGE(TAG, "NVM not ready");
this->error_code_ = ERROR_SENSOR_STATUS;
this->mark_failed();
this->mark_failed(LOG_STR("NVM not ready"));
return;
}
// verify status_nvm_err bit (it is asserted if an error is detected)
if (this->status_.bit.status_nvm_err) {
ESP_LOGE(TAG, "NVM error detected");
this->error_code_ = ERROR_SENSOR_STATUS;
this->mark_failed();
this->mark_failed(LOG_STR("NVM error detected"));
return;
}
@@ -176,10 +134,7 @@ void BMP581Component::setup() {
// enable the data ready interrupt source
if (!this->write_interrupt_source_settings_(true)) {
ESP_LOGE(TAG, "Failed to write interrupt source register");
this->error_code_ = ERROR_COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR("Failed to write interrupt source register"));
return;
}
@@ -198,10 +153,7 @@ void BMP581Component::setup() {
// write oversampling settings
if (!this->write_oversampling_settings_(this->temperature_oversampling_, this->pressure_oversampling_)) {
ESP_LOGE(TAG, "Failed to write oversampling register");
this->error_code_ = ERROR_COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR("Failed to write oversampling register"));
return;
}
@@ -218,19 +170,13 @@ void BMP581Component::setup() {
if ((this->iir_temperature_level_ != IIR_FILTER_OFF) || (this->iir_pressure_level_ != IIR_FILTER_OFF)) {
if (!this->write_iir_settings_(this->iir_temperature_level_, this->iir_pressure_level_)) {
ESP_LOGE(TAG, "Failed to write IIR configuration registers");
this->error_code_ = ERROR_COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR("Failed to write IIR configuration registers"));
return;
}
if (!this->prime_iir_filter_()) {
ESP_LOGE(TAG, "Failed to prime the IIR filter with an initial measurement");
this->error_code_ = ERROR_PRIME_IIR_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR("Failed to prime the IIR filter with an initial measurement"));
return;
}
@@ -133,15 +133,6 @@ class BMP581Component : public PollingComponent {
// Sets the power mode on the BMP581 by writing to the ODR register
bool write_power_mode_(OperationMode mode);
enum ErrorCode {
NONE = 0,
ERROR_COMMUNICATION_FAILED,
ERROR_WRONG_CHIP_ID,
ERROR_SENSOR_STATUS,
ERROR_SENSOR_RESET,
ERROR_PRIME_IIR_FAILED
} error_code_{NONE};
// BMP581's interrupt source register (address 0x15) to configure which interrupts are enabled (page 54 of datasheet)
union {
struct {
@@ -1,25 +0,0 @@
#pragma once
#include "esphome/core/defines.h"
#ifdef USE_BUTTON
#include "bq25186.h"
#include "esphome/components/button/button.h"
namespace esphome::bq25186 {
/// Writes one SHIP_RST field when pressed
class BQ25186Button final : public button::Button, public Parented<BQ25186Component> {
public:
BQ25186Button(uint8_t mask, uint8_t value) : mask_(mask), value_(value) {}
protected:
void press_action() override { this->parent_->write_ship_rst(this->mask_, this->value_); }
const uint8_t mask_;
const uint8_t value_;
};
} // namespace esphome::bq25186
#endif // USE_BUTTON
+4 -7
View File
@@ -1,4 +1,3 @@
import esphome.codegen as cg
from esphome.components import button
import esphome.config_validation as cv
from esphome.const import (
@@ -10,11 +9,10 @@ from esphome.const import (
)
from esphome.types import ConfigType
from . import BQ25186_CHILD_SCHEMA, CONF_BQ25186_ID, bq25186_ns
from . import BQ25186_CHILD_SCHEMA, CONF_BQ25186_ID
DEPENDENCIES = ["bq25186"]
BQ25186Button = bq25186_ns.class_("BQ25186Button", button.Button)
# SHIP_RST: bit 7 is the software reset, bits 6:5 the shutdown, ship and hardware reset codes
SOFTWARE_RESET_MASK = 0x80
@@ -33,7 +31,7 @@ CONFIG_SCHEMA = cv.All(
BQ25186_CHILD_SCHEMA.extend(
{
cv.Optional(key): button.button_schema(
BQ25186Button,
button.ApplyButton,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=icon,
device_class=device_class,
@@ -46,7 +44,6 @@ CONFIG_SCHEMA = cv.All(
async def to_code(config: ConfigType) -> None:
buttons = button.sub_buttons(config, parent=config[CONF_BQ25186_ID])
for key, mask, value, _, _ in _BUTTONS:
if (conf := config.get(key)) is not None:
var = await button.new_button(conf, mask, value)
await cg.register_parented(var, config[CONF_BQ25186_ID])
await buttons(key, None, apply=f"write_ship_rst({mask:#04x}, {value:#04x})")
+1 -4
View File
@@ -48,7 +48,7 @@ void BQ27220Component::setup() {
}
if (device_number != DEVICE_NUMBER) {
ESP_LOGE(TAG, "Unexpected device number 0x%04X (expected 0x%04X)", device_number, DEVICE_NUMBER);
this->mark_failed();
this->mark_failed(LOG_STR("Unexpected device number"));
}
}
@@ -76,9 +76,6 @@ void BQ27220Component::update() {
void BQ27220Component::dump_config() {
ESP_LOGCONFIG(TAG, "BQ27220 Battery Fuel Gauge:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
LOG_UPDATE_INTERVAL(this);
LOG_SENSOR(" ", "Voltage", this->voltage_sensor_);
LOG_SENSOR(" ", "Current", this->current_sensor_);
+7 -2
View File
@@ -18,6 +18,7 @@ from esphome.const import (
)
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
from esphome.core.entity_helpers import (
ApplyEntity,
SubEntities,
entity_duplicate_validator,
queue_entity_register,
@@ -41,6 +42,7 @@ DEVICE_CLASSES = [
button_ns = cg.esphome_ns.namespace("button")
Button = button_ns.class_("Button", cg.EntityBase)
ButtonPtr = Button.operator("ptr")
ApplyButton = button_ns.class_("ApplyButton", Button)
validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_")
@@ -116,11 +118,14 @@ async def new_button(config: ConfigType, *args: SafeExpType) -> MockObj:
return var
APPLY_ENTITY = ApplyEntity(ApplyButton, ((ButtonPtr, "entity"),))
def sub_buttons(
config: ConfigType, *, parent: MockObj | ID | None = None
) -> SubEntities:
"""Return a SubEntities bound to new_button."""
return SubEntities(new_button, config, parent)
"""Return a SubEntities bound to new_button; ``apply`` statements can use ``entity``."""
return SubEntities(new_button, config, parent, APPLY_ENTITY)
BUTTON_PRESS_SCHEMA = maybe_simple_id(
+10
View File
@@ -46,4 +46,14 @@ class Button : public EntityBase {
LazyCallbackManager<void()> press_callback_{};
};
/// Calls the codegen-generated Fn(this) on a press; the hub and any publish are baked into Fn.
template<auto Fn> class ApplyButton final : public Button {
public:
// Not "= default": placement new would zero-fill .bss that is already zero.
ApplyButton() {}
protected:
void press_action() override { Fn(this); }
};
} // namespace esphome::button
+1 -11
View File
@@ -37,8 +37,7 @@ void CAP1188Component::finish_setup_() {
this->read_byte(CAP1188_REVISION, &this->cap1188_revision_);
if ((this->cap1188_product_id_ != 0x50) || (this->cap1188_manufacture_id_ != 0x5D)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR("Product ID or Manufacture ID of the connected device does not match a known CAP1188"));
return;
}
@@ -70,15 +69,6 @@ void CAP1188Component::dump_config() {
this->cap1188_product_id_, this->cap1188_manufacture_id_, this->cap1188_revision_);
LOG_I2C_DEVICE(this);
LOG_PIN(" Reset Pin: ", this->reset_pin_);
switch (this->error_code_) {
case COMMUNICATION_FAILED:
ESP_LOGE(TAG, "Product ID or Manufacture ID of the connected device does not match a known CAP1188.");
break;
case NONE:
default:
break;
}
}
void CAP1188Component::loop() {
-5
View File
@@ -59,11 +59,6 @@ class CAP1188Component final : public Component, public i2c::I2CDevice {
uint8_t cap1188_product_id_{0};
uint8_t cap1188_manufacture_id_{0};
uint8_t cap1188_revision_{0};
enum ErrorCode {
NONE = 0,
COMMUNICATION_FAILED,
} error_code_{NONE};
};
} // namespace esphome::cap1188
+7 -31
View File
@@ -10,29 +10,28 @@ ESPHOME_LOG_TAG(TAG, "ccs811");
// based on
// - https://cdn.sparkfun.com/datasheets/BreakoutBoards/CCS811_Programming_Guide.pdf
#define CHECK_TRUE(f, error_code) \
#define CHECK_TRUE(f, message) \
if (!(f)) { \
this->mark_failed(); \
this->error_code_ = (error_code); \
this->mark_failed(LOG_STR(message)); \
return; \
}
#define CHECKED_IO(f) CHECK_TRUE(f, COMMUNICATION_FAILED)
#define CHECKED_IO(f) CHECK_TRUE(f, ESP_LOG_MSG_COMM_FAIL)
void CCS811Component::setup() {
// page 9 programming guide - hwid is always 0x81
uint8_t hw_id;
CHECKED_IO(this->read_byte(0x20, &hw_id))
CHECK_TRUE(hw_id == 0x81, INVALID_ID)
CHECK_TRUE(hw_id == 0x81, "Sensor reported an invalid ID. Is this a CCS811?")
// software reset, page 3 - allowed to fail
this->write_bytes(0xFF, {0x11, 0xE5, 0x72, 0x8A});
delay(5);
// page 10, APP_START
CHECK_TRUE(!this->status_has_error_(), SENSOR_REPORTED_ERROR)
CHECK_TRUE(this->status_app_is_valid_(), APP_INVALID)
CHECK_TRUE(this->write_bytes(0xF4, {}), APP_START_FAILED)
CHECK_TRUE(!this->status_has_error_(), "Sensor reported internal error")
CHECK_TRUE(this->status_app_is_valid_(), "Sensor reported invalid APP installed")
CHECK_TRUE(this->write_bytes(0xF4, {}), "Sensor reported APP start failed")
// App setup, wait for it to load
delay(1);
@@ -160,29 +159,6 @@ void CCS811Component::dump_config() {
} else {
ESP_LOGCONFIG(TAG, " Baseline: NOT SET");
}
if (this->is_failed()) {
switch (this->error_code_) {
case COMMUNICATION_FAILED:
ESP_LOGW(TAG, ESP_LOG_MSG_COMM_FAIL);
break;
case INVALID_ID:
ESP_LOGW(TAG, "Sensor reported an invalid ID. Is this a CCS811?");
break;
case SENSOR_REPORTED_ERROR:
ESP_LOGW(TAG, "Sensor reported internal error");
break;
case APP_INVALID:
ESP_LOGW(TAG, "Sensor reported invalid APP installed.");
break;
case APP_START_FAILED:
ESP_LOGW(TAG, "Sensor reported APP start failed.");
break;
case UNKNOWN:
default:
ESP_LOGW(TAG, "Unknown setup error!");
break;
}
}
}
} // namespace esphome::ccs811
-9
View File
@@ -31,15 +31,6 @@ class CCS811Component final : public PollingComponent, public i2c::I2CDevice {
bool status_has_data_() { return this->read_status_().value_or(0) & (1 << 3); }
void send_env_data_();
enum ErrorCode {
UNKNOWN,
COMMUNICATION_FAILED,
INVALID_ID,
SENSOR_REPORTED_ERROR,
APP_INVALID,
APP_START_FAILED,
} error_code_{UNKNOWN};
sensor::Sensor *co2_{nullptr};
sensor::Sensor *tvoc_{nullptr};
text_sensor::TextSensor *version_{nullptr};
+1 -4
View File
@@ -18,7 +18,7 @@ void CH422GComponent::setup() {
// Set mode and check for errors
if (!this->set_mode_(this->mode_value_) || !this->read_inputs_()) {
ESP_LOGE(TAG, "CH422G not detected at 0x%02X", this->address_);
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
@@ -34,9 +34,6 @@ void CH422GComponent::loop() {
void CH422GComponent::dump_config() {
ESP_LOGCONFIG(TAG, "CH422G:");
LOG_I2C_DEVICE(this)
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
}
void CH422GComponent::pin_mode(uint8_t pin, gpio::Flags flags) {
+2 -8
View File
@@ -24,8 +24,7 @@ void CH423Component::setup() {
success = this->read_inputs_();
}
if (!success) {
ESP_LOGE(TAG, "CH423 not detected");
this->mark_failed();
this->mark_failed(LOG_STR("CH423 not detected"));
return;
}
@@ -38,12 +37,7 @@ void CH423Component::loop() {
this->pin_read_flags_ = 0x00;
}
void CH423Component::dump_config() {
ESP_LOGCONFIG(TAG, "CH423:");
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
}
void CH423Component::dump_config() { ESP_LOGCONFIG(TAG, "CH423:"); }
void CH423Component::pin_mode(uint8_t pin, gpio::Flags flags) {
if (pin < 8) {
+1 -5
View File
@@ -27,8 +27,7 @@ uint8_t cm1106_checksum(const uint8_t *response, size_t len) {
void CM1106Component::setup() {
uint8_t response[8] = {0};
if (!this->cm1106_write_command_(C_M1106_CMD_GET_CO2, sizeof(C_M1106_CMD_GET_CO2), response, sizeof(response))) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
@@ -139,9 +138,6 @@ void CM1106Component::dump_config() {
" ABC baseline: %uppm",
ONOFF(this->abc_boot_logic_ == CM1106_ABC_ENABLED), this->abc_cycle_, this->abc_baseline_);
}
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
}
} // namespace esphome::cm1106
+1
View File
@@ -54,6 +54,7 @@ CONF_ON_STATE_CHANGE = "on_state_change"
CONF_ON_STOP = "on_stop"
CONF_OUT_PIN_LEVEL = "out_pin_level"
CONF_PARITY = "parity"
CONF_QUERY_PARAMS = "query_params"
CONF_RECEIVER_FREQUENCY = "receiver_frequency"
CONF_RECONNECT_INTERVAL = "reconnect_interval"
CONF_RED_CHANNEL = "red_channel"
+1 -4
View File
@@ -67,15 +67,12 @@ void CSE7761Component::setup() {
ESP_LOGD(TAG, "CSE7761 found");
this->data_.ready = true;
} else {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
}
}
void CSE7761Component::dump_config() {
ESP_LOGCONFIG(TAG, "CSE7761:");
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
ESP_LOGCONFIG(TAG, " Current input: %s",
LOG_STR_ARG(this->is_current_transformer_() ? LOG_STR("current transformer") : LOG_STR("shunt")));
LOG_UPDATE_INTERVAL(this);
@@ -23,8 +23,7 @@ void DAC7678Output::setup() {
// Reset device
if (!this->write_byte_16(DAC7678_REG_SOFTWARE_RESET, 0x0000)) {
ESP_LOGE(TAG, "Reset failed");
this->mark_failed();
this->mark_failed(LOG_STR("Reset failed"));
return;
} else {
ESP_LOGV(TAG, "Reset succeeded");
@@ -35,8 +34,7 @@ void DAC7678Output::setup() {
// Set internal reference
if (this->internal_reference_) {
if (!this->write_byte_16(DAC7678_REG_INTERNAL_REF_0, 1 << 4)) {
ESP_LOGE(TAG, "Set internal reference failed");
this->mark_failed();
this->mark_failed(LOG_STR("Set internal reference failed"));
return;
} else {
ESP_LOGV(TAG, "Internal reference enabled");
@@ -45,9 +43,7 @@ void DAC7678Output::setup() {
}
void DAC7678Output::dump_config() {
if (this->is_failed()) {
ESP_LOGE(TAG, "Setting up DAC7678 failed!");
} else {
if (!this->is_failed()) {
ESP_LOGCONFIG(TAG, "DAC7678 initialised");
}
}
@@ -26,17 +26,22 @@ class DfrobotSen0395SettingsAction final : public Action<Ts...>, public Parented
TEMPLATABLE_VALUE(float, det_min4)
TEMPLATABLE_VALUE(float, det_max4)
void play(const Ts &...x) {
void play(const Ts &...x) override {
this->parent_->enqueue(make_unique<PowerCommand>(0));
if (this->factory_reset_.has_value() && this->factory_reset_.value(x...) == true) {
this->parent_->enqueue(make_unique<FactoryResetCommand>());
}
if (this->det_min1_.has_value() && this->det_max1_.has_value()) {
if (this->det_min1_.value() >= 0 && this->det_max1_.value() >= 0) {
this->parent_->enqueue(make_unique<DetRangeCfgCommand>(
this->det_min1_.value_or(-1), this->det_max1_.value_or(-1), this->det_min2_.value_or(-1),
this->det_max2_.value_or(-1), this->det_min3_.value_or(-1), this->det_max3_.value_or(-1),
this->det_min4_.value_or(-1), this->det_max4_.value_or(-1)));
// Each segment is read once, so the guard and the command see the same values.
const float min1 = this->det_min1_.value(x...);
if (min1 >= 0) {
const float max1 = this->det_max1_.value(x...);
if (max1 >= 0) {
this->parent_->enqueue(make_unique<DetRangeCfgCommand>(
min1, max1, this->det_min2_.value_or(x..., -1), this->det_max2_.value_or(x..., -1),
this->det_min3_.value_or(x..., -1), this->det_max3_.value_or(x..., -1),
this->det_min4_.value_or(x..., -1), this->det_max4_.value_or(x..., -1)));
}
}
}
if (this->delay_after_detect_.has_value() && this->delay_after_disappear_.has_value()) {
@@ -0,0 +1,57 @@
import esphome.codegen as cg
from esphome.components import button
from esphome.components.const import CONF_QUERY_PARAMS
import esphome.config_validation as cv
from esphome.const import (
CONF_FACTORY_RESET,
CONF_ID,
CONF_RESTART,
DEVICE_CLASS_RESTART,
ENTITY_CATEGORY_CONFIG,
ENTITY_CATEGORY_DIAGNOSTIC,
ICON_DATABASE,
ICON_RESTART,
ICON_RESTART_ALERT,
)
from esphome.types import ConfigType
from .. import CONF_DFROBOT_SEN0609_ID, DFRobotSEN0609Component, dfrobot_sen0609_ns
DFRobotSEN0609Button = dfrobot_sen0609_ns.class_("DFRobotSEN0609Button", button.Button)
ButtonAction = dfrobot_sen0609_ns.enum("ButtonAction")
CONFIG_SCHEMA = {
cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase),
cv.GenerateID(CONF_DFROBOT_SEN0609_ID): cv.use_id(DFRobotSEN0609Component),
cv.Optional(CONF_FACTORY_RESET): button.button_schema(
DFRobotSEN0609Button,
device_class=DEVICE_CLASS_RESTART,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_RESTART_ALERT,
),
cv.Optional(CONF_QUERY_PARAMS): button.button_schema(
DFRobotSEN0609Button,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
icon=ICON_DATABASE,
),
cv.Optional(CONF_RESTART): button.button_schema(
DFRobotSEN0609Button,
device_class=DEVICE_CLASS_RESTART,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
icon=ICON_RESTART,
),
}
async def to_code(config: ConfigType) -> None:
hub = await cg.get_variable(config[CONF_DFROBOT_SEN0609_ID])
buttons = button.sub_buttons(config, parent=hub)
await buttons(
CONF_FACTORY_RESET,
hub.set_factory_reset_button,
ButtonAction.BUTTON_FACTORY_RESET,
)
await buttons(
CONF_QUERY_PARAMS, hub.set_query_button, ButtonAction.BUTTON_QUERY_PARAMS
)
await buttons(CONF_RESTART, hub.set_restart_button, ButtonAction.BUTTON_RESTART)
@@ -0,0 +1,30 @@
#pragma once
#include "esphome/components/button/button.h"
#include "../dfrobot_sen0609.h"
namespace esphome::dfrobot_sen0609 {
class DFRobotSEN0609Button final : public button::Button, public Parented<DFRobotSEN0609Component> {
public:
explicit DFRobotSEN0609Button(ButtonAction action) : action_(action) {}
protected:
void press_action() override {
switch (this->action_) {
case BUTTON_RESTART:
this->parent_->restart();
break;
case BUTTON_FACTORY_RESET:
this->parent_->factory_reset();
break;
case BUTTON_QUERY_PARAMS:
this->parent_->query_params();
break;
}
}
ButtonAction action_;
};
} // namespace esphome::dfrobot_sen0609
@@ -21,6 +21,9 @@ static constexpr uint32_t COMMAND_GAP_MS = 100;
static constexpr uint32_t COALESCE_MS = 1000;
static constexpr uint32_t DEFAULT_TIMEOUT_MS = 1000;
static constexpr uint32_t LONG_TIMEOUT_MS = 2000;
static constexpr uint32_t FACTORY_RESET_TIMEOUT_MS = 3000;
// resetSystem has no answer; this is how long the module takes to boot again
static constexpr uint32_t RESTART_MS = 1500;
static constexpr uint32_t GIVE_UP_BACKOFF_MS = 30000;
// Presence frames come every second (setUartOutput period); this long without one means the module lost them
static constexpr uint32_t FRAME_TIMEOUT_MS = 10000;
@@ -113,6 +116,10 @@ static const LogString *operation_to_str(Operation operation) {
return LOG_STR("stop");
case Operation::OPERATION_START:
return LOG_STR("start");
case Operation::OPERATION_RESTART:
return LOG_STR("restart");
case Operation::OPERATION_FACTORY_RESET:
return LOG_STR("factory reset");
case Operation::OPERATION_WRITE:
return LOG_STR("write");
case Operation::OPERATION_SAVE:
@@ -161,6 +168,11 @@ void DFRobotSEN0609Component::dump_config() {
#ifdef USE_SELECT
LOG_SELECT(" ", "OutPinLevel", this->out_pin_level_select_);
#endif
#ifdef USE_BUTTON
LOG_BUTTON(" ", "FactoryReset", this->factory_reset_button_);
LOG_BUTTON(" ", "Query", this->query_button_);
LOG_BUTTON(" ", "Restart", this->restart_button_);
#endif
}
void DFRobotSEN0609Component::setup() {
@@ -436,6 +448,21 @@ void DFRobotSEN0609Component::request_write_(Param param) {
this->hold_(COALESCE_MS);
}
void DFRobotSEN0609Component::restart() {
this->restart_pending_ = true;
this->hold_(COMMAND_GAP_MS);
}
void DFRobotSEN0609Component::factory_reset() {
this->factory_reset_pending_ = true;
this->hold_(COMMAND_GAP_MS);
}
void DFRobotSEN0609Component::query_params() {
this->pending_reads_ |= this->wanted_reads_();
this->hold_(COMMAND_GAP_MS);
}
#ifdef USE_NUMBER
void DFRobotSEN0609Component::control_number(NumberSetting setting, float value) {
// The module needs min_range <= trigger_range <= max_range; a value not read yet is NAN and passes
@@ -511,20 +538,42 @@ void DFRobotSEN0609Component::hold_(uint32_t duration_ms) {
void DFRobotSEN0609Component::run_sequencer_() {
const uint32_t now = App.get_loop_component_start_time();
if (this->operation_ != Operation::OPERATION_NONE) {
const bool slow = this->operation_ == Operation::OPERATION_STOP || this->operation_ == Operation::OPERATION_SAVE;
if (now - this->sent_ms_ < (slow ? LONG_TIMEOUT_MS : DEFAULT_TIMEOUT_MS))
uint32_t timeout = DEFAULT_TIMEOUT_MS;
switch (this->operation_) {
case Operation::OPERATION_RESTART:
timeout = RESTART_MS;
break;
case Operation::OPERATION_FACTORY_RESET:
timeout = FACTORY_RESET_TIMEOUT_MS;
break;
case Operation::OPERATION_STOP:
case Operation::OPERATION_SAVE:
timeout = LONG_TIMEOUT_MS;
break;
default:
break;
}
if (now - this->sent_ms_ < timeout)
return;
ESP_LOGD(TAG, "No answer to '%s'", this->command_);
this->fail_operation_();
if (this->operation_ == Operation::OPERATION_RESTART) {
this->finish_operation_();
} else {
ESP_LOGD(TAG, "No answer to '%s'", this->command_);
this->fail_operation_();
}
return;
}
if (now - this->hold_start_ms_ < this->hold_ms_)
return;
const bool work_pending = this->save_pending_ || this->pending_writes_ != 0 || this->pending_reads_ != 0;
const bool work_pending =
this->factory_reset_pending_ || this->save_pending_ || this->pending_writes_ != 0 || this->pending_reads_ != 0;
Operation operation;
Param param = PARAM_COUNT;
if (!work_pending) {
if (this->restart_pending_) {
// The reboot drops a write the module took but did not save; writes not sent yet are kept for after it
operation = this->stopped_ && this->save_pending_ ? Operation::OPERATION_SAVE : Operation::OPERATION_RESTART;
} else if (!work_pending) {
if (!this->stopped_) {
this->check_frames_(now);
// Work given up on is tried again in a later sequence, so the sensor runs in between
@@ -539,6 +588,8 @@ void DFRobotSEN0609Component::run_sequencer_() {
operation = Operation::OPERATION_START;
} else if (!this->stopped_) {
operation = Operation::OPERATION_STOP;
} else if (this->factory_reset_pending_) {
operation = Operation::OPERATION_FACTORY_RESET;
} else if (this->pending_writes_ != 0) {
operation = Operation::OPERATION_WRITE;
param = static_cast<Param>(__builtin_ctz(this->pending_writes_));
@@ -611,6 +662,12 @@ bool DFRobotSEN0609Component::build_command_(Operation operation, Param param) {
case Operation::OPERATION_START:
ESPHOME_strncpy_P(buf, ESPHOME_PSTR("sensorStart"), len);
return true;
case Operation::OPERATION_RESTART:
ESPHOME_strncpy_P(buf, ESPHOME_PSTR("resetSystem"), len);
return true;
case Operation::OPERATION_FACTORY_RESET:
ESPHOME_strncpy_P(buf, ESPHOME_PSTR("resetCfg"), len);
return true;
case Operation::OPERATION_SAVE:
ESPHOME_strncpy_P(buf, ESPHOME_PSTR("saveConfig"), len);
return true;
@@ -785,6 +842,16 @@ void DFRobotSEN0609Component::finish_operation_() {
this->status_clear_warning();
this->sequence_failed_ = false;
break;
case Operation::OPERATION_RESTART:
// The module starts sensing on its own after a reboot
this->restart_pending_ = false;
this->stopped_ = false;
this->queue_configuration_();
break;
case Operation::OPERATION_FACTORY_RESET:
this->factory_reset_pending_ = false;
this->queue_configuration_();
break;
case Operation::OPERATION_WRITE:
this->deferred_writes_ &= ~param_bit(this->param_);
if (PERSISTENT_PARAMS & param_bit(this->param_))
@@ -846,6 +913,12 @@ void DFRobotSEN0609Component::fail_operation_() {
ESP_LOGW(TAG, "Giving up on %s '%s'", LOG_STR_ARG(operation_to_str(operation)), this->command_);
this->sequence_failed_ = true;
switch (operation) {
case Operation::OPERATION_RESTART:
this->restart_pending_ = false;
break;
case Operation::OPERATION_FACTORY_RESET:
this->factory_reset_pending_ = false;
break;
case Operation::OPERATION_WRITE:
#ifdef USE_SWITCH
if (is_led(this->param_)) {
@@ -21,6 +21,9 @@
#ifdef USE_SELECT
#include "esphome/components/select/select.h"
#endif
#ifdef USE_BUTTON
#include "esphome/components/button/button.h"
#endif
#include "esphome/components/uart/uart.h"
#include <array>
@@ -58,6 +61,12 @@ enum SwitchSetting : uint8_t {
SWITCH_COUNT,
};
enum ButtonAction : uint8_t {
BUTTON_RESTART,
BUTTON_FACTORY_RESET,
BUTTON_QUERY_PARAMS,
};
/// Module parameters; a write or read of each is one command. Pending work runs in this order.
enum Param : uint8_t {
PARAM_RUN_APP,
@@ -81,6 +90,8 @@ enum class Operation : uint8_t {
OPERATION_NONE,
OPERATION_STOP,
OPERATION_START,
OPERATION_RESTART,
OPERATION_FACTORY_RESET,
OPERATION_WRITE,
OPERATION_SAVE,
OPERATION_READ,
@@ -102,6 +113,11 @@ class DFRobotSEN0609Component final : public Component, public uart::UARTDevice
#ifdef USE_SELECT
SUB_SELECT(out_pin_level)
#endif
#ifdef USE_BUTTON
SUB_BUTTON(factory_reset)
SUB_BUTTON(query)
SUB_BUTTON(restart)
#endif
public:
explicit DFRobotSEN0609Component(RunMode mode);
@@ -121,6 +137,12 @@ class DFRobotSEN0609Component final : public Component, public uart::UARTDevice
#ifdef USE_SELECT
void control_out_pin_level(size_t index);
#endif
/// Reboot the module, then apply the configuration and read the settings again.
void restart();
/// Restore the module's factory settings, then apply the configuration and read the settings again.
void factory_reset();
/// Read all settings shown by entities from the module.
void query_params();
protected:
void readline_(uint8_t c);
@@ -207,6 +229,8 @@ class DFRobotSEN0609Component final : public Component, public uart::UARTDevice
bool stopped_{false};
bool save_pending_{false};
bool deferred_save_{false};
bool restart_pending_{false};
bool factory_reset_pending_{false};
bool sequence_failed_{false};
};
+1 -4
View File
@@ -35,16 +35,13 @@ void DHT12Component::update() {
void DHT12Component::setup() {
uint8_t data[5];
if (!this->read_data_(data)) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
}
void DHT12Component::dump_config() {
ESP_LOGD(TAG, "DHT12:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
}
+50 -11
View File
@@ -57,17 +57,17 @@ void Display::line_at_angle(int x, int y, int angle, int start_radius, int stop_
// -Os stops inlining it once there are two call sites, which costs a call and
// spills per pixel. Without PSRAM there is one call site and it changes
// nothing, and draw_pixel_at() stays a virtual call either way.
template<ColorBitness BITNESS>
static void __attribute__((flatten))
draw_packed_pixels(Display *display, int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
bool big_endian, int x_offset, int y_offset, int x_pad) {
// HIGH_BYTE_FIRST (big endian) only matters for 565; as a template argument its test leaves the pixel loop.
template<ColorBitness BITNESS, bool HIGH_BYTE_FIRST = false>
static void __attribute__((flatten)) draw_packed_pixels(Display *display, int x_start, int y_start, int w, int h,
const uint8_t *ptr, int x_offset, int y_offset, int x_pad) {
const size_t line_stride = x_offset + w + x_pad; // length of each source line in pixels
// BITNESS is a constant here, so to_color()'s three per pixel divisions
// become a multiply and shift and its bitness switch folds.
const auto draw_source_pixel = [&](int x, int y, size_t source_idx) ESPHOME_ALWAYS_INLINE {
display->draw_pixel_at(
x + x_start, y + y_start,
ColorUtil::to_color(ColorUtil::read_packed<BITNESS>(ptr, source_idx, big_endian), order, BITNESS));
ColorUtil::to_color(ColorUtil::read_packed<BITNESS>(ptr, source_idx, HIGH_BYTE_FIRST), BITNESS));
};
// The source and frame buffers are row-major, so walking rows keeps the read
// and the write sequential. When the display swaps the axes before writing,
@@ -94,20 +94,59 @@ draw_packed_pixels(Display *display, int x_start, int y_start, int w, int h, con
}
}
// Remove before 2027.5.0. Draws a block in the deprecated BGR or GRB order, pixel by pixel. Not inlined, so
// the RGB loops above compile as tightly as before.
static void __attribute__((noinline))
draw_ordered_pixels(Display *display, int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) {
const size_t line_stride = x_offset + w + x_pad;
for (int y = 0; y != h; y++) {
size_t source_idx = (y_offset + y) * line_stride + x_offset;
for (int x = 0; x != w; x++, source_idx++) {
uint32_t code;
if (bitness == COLOR_BITNESS_565) {
code = ColorUtil::read_packed<COLOR_BITNESS_565>(ptr, source_idx, big_endian);
} else if (bitness == COLOR_BITNESS_888) {
code = ColorUtil::read_packed<COLOR_BITNESS_888>(ptr, source_idx, big_endian);
} else {
code = ColorUtil::read_packed<COLOR_BITNESS_332>(ptr, source_idx, big_endian);
}
display->draw_pixel_at(x + x_start, y + y_start, apply_color_order(ColorUtil::to_color(code, bitness), order));
}
}
}
void Display::draw_pixels_internal(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorBitness bitness,
bool big_endian, int x_offset, int y_offset, int x_pad) {
// Through the deprecated form, so a driver that still overrides only that one keeps its fast path.
// Remove before 2027.5.0, when the per pixel drawing below moves here.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
this->draw_pixels_at(x_start, y_start, w, h, ptr, COLOR_ORDER_RGB, bitness, big_endian, x_offset, y_offset, x_pad);
#pragma GCC diagnostic pop
}
// Must not call draw_pixels_at() without a color order or draw_pixels_internal(): those call this, and a legacy
// override's fallback ends up here.
void Display::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) {
if (order != COLOR_ORDER_RGB) {
draw_ordered_pixels(this, x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad);
return;
}
switch (bitness) {
case COLOR_BITNESS_565:
draw_packed_pixels<COLOR_BITNESS_565>(this, x_start, y_start, w, h, ptr, order, big_endian, x_offset, y_offset,
x_pad);
if (big_endian) {
draw_packed_pixels<COLOR_BITNESS_565, true>(this, x_start, y_start, w, h, ptr, x_offset, y_offset, x_pad);
} else {
draw_packed_pixels<COLOR_BITNESS_565, false>(this, x_start, y_start, w, h, ptr, x_offset, y_offset, x_pad);
}
break;
case COLOR_BITNESS_888:
draw_packed_pixels<COLOR_BITNESS_888>(this, x_start, y_start, w, h, ptr, order, big_endian, x_offset, y_offset,
x_pad);
draw_packed_pixels<COLOR_BITNESS_888>(this, x_start, y_start, w, h, ptr, x_offset, y_offset, x_pad);
break;
default:
draw_packed_pixels<COLOR_BITNESS_332>(this, x_start, y_start, w, h, ptr, order, big_endian, x_offset, y_offset,
x_pad);
draw_packed_pixels<COLOR_BITNESS_332>(this, x_start, y_start, w, h, ptr, x_offset, y_offset, x_pad);
break;
}
}
+40 -6
View File
@@ -346,8 +346,6 @@ class Display : public PollingComponent {
virtual void draw_pixel_at(int x, int y, Color color) = 0;
/** Given an array of pixels encoded in the nominated format, draw these into the display's buffer.
* The naive implementation here will work in all cases, but can be overridden by sub-classes
* in order to optimise the procedure.
* The parameters describe a rectangular block of pixels, potentially within a larger buffer.
*
* \param x_start The starting destination x position
@@ -355,23 +353,49 @@ class Display : public PollingComponent {
* \param w the width of the pixel block
* \param h the height of the pixel block
* \param ptr A pointer to the start of the data to be copied
* \param order The ordering of the colors
* \param bitness Defines the number of bits and their format for each pixel
* \param bitness Defines the number of bits and their format for each pixel. Red is always in the
* most significant bits.
* \param big_endian True if 16 bit values are stored big-endian. Ignored for 888, which is always b,g,r
* in memory for RGB order, as LVGL and ESPHome images store it.
* in memory, as LVGL and ESPHome images store it.
* \param x_offset The initial x-offset into the source buffer.
* \param y_offset The initial y-offset into the source buffer.
* \param x_pad How many pixels are in each line after the end of the pixels to be copied.
*
* The length of each source buffer line (stride) will be x_offset + w + x_pad.
* The block must lie on the screen. A driver that can copy blocks itself overrides draw_pixels_internal().
*/
void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorBitness bitness, bool big_endian,
int x_offset, int y_offset, int x_pad) {
this->draw_pixels_internal(x_start, y_start, w, h, ptr, bitness, big_endian, x_offset, y_offset, x_pad);
}
/// Convenience overload for base case where the pixels are packed into the buffer with no gaps (e.g. suits LVGL.)
void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorBitness bitness,
bool big_endian) {
this->draw_pixels_internal(x_start, y_start, w, h, ptr, bitness, big_endian, 0, 0, 0);
}
// Remove before 2027.5.0
/// The block form above with a color order. The base version draws per pixel and honors the order;
/// a driver that still overrides this one keeps receiving every block, since draw_pixels_internal() calls it.
/// Such a driver needs `using display::Display::draw_pixels_at;` so the forms above stay visible through it,
/// and its fallback must call Display::draw_pixels_at() with the order: Display::draw_pixels_internal() would
/// call the override again.
ESPDEPRECATED(
"Pixels are always RGB: call draw_pixels_at() without the ColorOrder, and override draw_pixels_internal() "
"to copy blocks. Removed in 2027.5.0",
"2026.11.0")
virtual void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad);
/// Convenience overload for base case where the pixels are packed into the buffer with no gaps (e.g. suits LVGL.)
// Remove before 2027.5.0
ESPDEPRECATED("Pixels are always RGB, drop the ColorOrder argument. Removed in 2027.5.0", "2026.11.0")
void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
ColorBitness bitness, bool big_endian) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
this->draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, 0, 0, 0);
#pragma GCC diagnostic pop
}
/// Draw a straight line from the point [x1,y1] to [x2,y2] with the given color.
@@ -792,6 +816,16 @@ class Display : public PollingComponent {
void show_test_card() { this->show_test_card_ = true; }
protected:
/** Draws a block for draw_pixels_at(); the parameters are the same. The base version draws it per pixel
* through draw_pixel_at(), so it works on any display.
*
* A driver can override it to copy blocks that are already laid out the way its own draw_pixel_at()
* writes, and must send any other format, byte order, a software rotation or an active clipping
* rectangle through Display::draw_pixels_internal(), which draws per pixel. Do not also override the
* deprecated draw_pixels_at() with a color order: Display::draw_pixels_internal() calls it.
*/
virtual void draw_pixels_internal(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorBitness bitness,
bool big_endian, int x_offset, int y_offset, int x_pad);
bool clamp_x_(int x, int w, int &min_x, int &max_x);
bool clamp_y_(int y, int h, int &min_y, int &max_y);
void vprintf_(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format,
+101 -77
View File
@@ -9,6 +9,38 @@ enum ColorOrder : uint8_t { COLOR_ORDER_RGB = 0, COLOR_ORDER_BGR = 1, COLOR_ORDE
enum ColorBitness : uint8_t { COLOR_BITNESS_888 = 0, COLOR_BITNESS_565 = 1, COLOR_BITNESS_332 = 2 };
inline static uint8_t esp_scale(uint8_t i, uint8_t scale, uint8_t max_value = 255) { return (max_value * i / scale); }
/// esp_scale(value, (1 << bits) - 1) for a field of 2, 3, 5, 6 or 8 bits, as a multiply and shift that gives the
/// same result for every field value. With bits a constant this avoids a division.
constexpr uint8_t expand_field(uint8_t value, uint8_t bits) {
switch (bits) {
case 2:
return (value * 170) >> 1;
case 3:
return (value * 583) >> 4;
case 5:
return (value * 1053) >> 7;
case 6:
return (value * 4145) >> 10;
case 8:
return value;
default:
return esp_scale(value, (1 << bits) - 1);
}
}
// Remove before 2027.5.0, with the forms that take a color order. Maps a color read in RGB order to the
// given order, by moving its channels.
inline Color apply_color_order(Color color, ColorOrder order) {
switch (order) {
case COLOR_ORDER_BGR:
return Color(color.b, color.g, color.r);
case COLOR_ORDER_GRB:
return Color(color.g, color.r, color.b);
default:
return color;
}
}
class ColorUtil {
public:
/// Reads one packed pixel of the given bitness from a source buffer into the
@@ -23,7 +55,7 @@ class ColorUtil {
return (ptr[idx] << 8) + ptr[idx + 1];
return ptr[idx] + (ptr[idx + 1] << 8);
} else if constexpr (BITNESS == COLOR_BITNESS_888) {
// Always the LVGL RGB888 layout, b,g,r in memory for RGB order; byte order applies to 565 only
// Always the LVGL RGB888 layout, b,g,r in memory; byte order applies to 565 only
const size_t idx = index * 3;
return ptr[idx + 0] + (ptr[idx + 1] << 8) + (ptr[idx + 2] << 16);
} else {
@@ -31,9 +63,9 @@ class ColorUtil {
}
}
static Color to_color(uint32_t colorcode, ColorOrder color_order,
ColorBitness color_bitness = ColorBitness::COLOR_BITNESS_888, bool right_bit_aligned = true) {
uint8_t first_color, second_color, third_color;
/// Unpacks a color of the given bitness, red in the most significant bits.
static Color to_color(uint32_t colorcode, ColorBitness color_bitness = ColorBitness::COLOR_BITNESS_888,
bool right_bit_aligned = true) {
uint8_t first_bits = 0;
uint8_t second_bits = 0;
uint8_t third_bits = 0;
@@ -56,74 +88,66 @@ class ColorUtil {
break;
}
first_color = right_bit_aligned ? esp_scale(((colorcode >> (second_bits + third_bits)) & ((1 << first_bits) - 1)),
((1 << first_bits) - 1))
: esp_scale(((colorcode >> 16) & 0xFF), (1 << first_bits) - 1);
const uint8_t red =
right_bit_aligned
? expand_field((colorcode >> (second_bits + third_bits)) & ((1 << first_bits) - 1), first_bits)
: esp_scale(((colorcode >> 16) & 0xFF), (1 << first_bits) - 1);
second_color = right_bit_aligned
? esp_scale(((colorcode >> third_bits) & ((1 << second_bits) - 1)), ((1 << second_bits) - 1))
: esp_scale(((colorcode >> 8) & 0xFF), ((1 << second_bits) - 1));
const uint8_t green = right_bit_aligned
? expand_field((colorcode >> third_bits) & ((1 << second_bits) - 1), second_bits)
: esp_scale(((colorcode >> 8) & 0xFF), ((1 << second_bits) - 1));
third_color = (right_bit_aligned ? esp_scale(((colorcode >> 0) & ((1 << third_bits) - 1)), ((1 << third_bits) - 1))
: esp_scale(((colorcode >> 0) & 0xFF), (1 << third_bits) - 1));
const uint8_t blue = right_bit_aligned ? expand_field(colorcode & ((1 << third_bits) - 1), third_bits)
: esp_scale(((colorcode >> 0) & 0xFF), (1 << third_bits) - 1);
Color color_return;
switch (color_order) {
case COLOR_ORDER_RGB:
color_return.r = first_color;
color_return.g = second_color;
color_return.b = third_color;
break;
case COLOR_ORDER_BGR:
color_return.b = first_color;
color_return.g = second_color;
color_return.r = third_color;
break;
case COLOR_ORDER_GRB:
color_return.g = first_color;
color_return.r = second_color;
color_return.b = third_color;
break;
}
return color_return;
return Color(red, green, blue);
}
// Remove before 2027.5.0
ESPDEPRECATED("Packed colors are always RGB, drop the ColorOrder argument. Removed in 2027.5.0", "2026.11.0")
static Color to_color(uint32_t colorcode, ColorOrder color_order,
ColorBitness color_bitness = ColorBitness::COLOR_BITNESS_888, bool right_bit_aligned = true) {
return apply_color_order(to_color(colorcode, color_bitness, right_bit_aligned), color_order);
}
static inline Color rgb332_to_color(uint8_t rgb332_color) {
return to_color((uint32_t) rgb332_color, COLOR_ORDER_RGB, COLOR_BITNESS_332);
return to_color((uint32_t) rgb332_color, COLOR_BITNESS_332);
}
static uint8_t color_to_332(Color color, ColorOrder color_order = ColorOrder::COLOR_ORDER_RGB) {
uint16_t red_color, green_color, blue_color;
red_color = esp_scale8(color.red, ((1 << 3) - 1));
green_color = esp_scale8(color.green, ((1 << 3) - 1));
blue_color = esp_scale8(color.blue, (1 << 2) - 1);
switch (color_order) {
case COLOR_ORDER_RGB:
return red_color << 5 | green_color << 2 | blue_color;
case COLOR_ORDER_BGR:
return blue_color << 6 | green_color << 3 | red_color;
case COLOR_ORDER_GRB:
return green_color << 5 | red_color << 2 | blue_color;
}
return 0;
static uint8_t color_to_332(Color color) {
const uint16_t red_color = esp_scale8(color.red, ((1 << 3) - 1));
const uint16_t green_color = esp_scale8(color.green, ((1 << 3) - 1));
const uint16_t blue_color = esp_scale8(color.blue, (1 << 2) - 1);
return red_color << 5 | green_color << 2 | blue_color;
}
static uint16_t color_to_565(Color color, ColorOrder color_order = ColorOrder::COLOR_ORDER_RGB) {
uint16_t red_color, green_color, blue_color;
red_color = esp_scale8(color.red, ((1 << 5) - 1));
green_color = esp_scale8(color.green, ((1 << 6) - 1));
blue_color = esp_scale8(color.blue, (1 << 5) - 1);
// Remove before 2027.5.0
ESPDEPRECATED("Packed colors are always RGB, drop the ColorOrder argument. Removed in 2027.5.0", "2026.11.0")
static uint8_t color_to_332(Color color, ColorOrder color_order) {
if (color_order == COLOR_ORDER_RGB)
return color_to_332(color);
// The other orders move the 2 bit field, so they cannot reuse the RGB packing
const uint16_t red_color = esp_scale8(color.red, ((1 << 3) - 1));
const uint16_t green_color = esp_scale8(color.green, ((1 << 3) - 1));
if (color_order == COLOR_ORDER_BGR)
return esp_scale8(color.blue, (1 << 2) - 1) << 6 | green_color << 3 | red_color;
return green_color << 5 | red_color << 2 | esp_scale8(color.blue, (1 << 2) - 1);
}
static uint16_t color_to_565(Color color) {
const uint16_t red_color = esp_scale8(color.red, ((1 << 5) - 1));
const uint16_t green_color = esp_scale8(color.green, ((1 << 6) - 1));
const uint16_t blue_color = esp_scale8(color.blue, (1 << 5) - 1);
return red_color << 11 | green_color << 5 | blue_color;
}
// Remove before 2027.5.0
ESPDEPRECATED("Packed colors are always RGB, drop the ColorOrder argument. Removed in 2027.5.0", "2026.11.0")
static uint16_t color_to_565(Color color, ColorOrder color_order) {
switch (color_order) {
case COLOR_ORDER_RGB:
return red_color << 11 | green_color << 5 | blue_color;
case COLOR_ORDER_BGR:
return blue_color << 11 | green_color << 5 | red_color;
return color_to_565(Color(color.b, color.g, color.r));
case COLOR_ORDER_GRB:
return green_color << 10 | red_color << 5 | blue_color;
// Green moves to the 5 bit field at the top, so it cannot reuse the RGB packing
return esp_scale8(color.green, (1 << 6) - 1) << 10 | esp_scale8(color.red, (1 << 5) - 1) << 5 |
esp_scale8(color.blue, (1 << 5) - 1);
default:
return color_to_565(color);
}
return 0;
}
static uint32_t color_to_grayscale4(Color color) {
uint32_t gs4 = esp_scale8(color.white, 15);
@@ -196,23 +220,13 @@ constexpr uint8_t color_to_mono(Color color) { return rec601_luma(color) >= 128
*/
class Rgb565ToMono {
public:
Rgb565ToMono() { this->fill_tables_(REC601_LUMA_R, REC601_LUMA_G, REC601_LUMA_B); }
// Remove before 2027.5.0
ESPDEPRECATED("Packed colors are always RGB, drop the ColorOrder argument. Removed in 2027.5.0", "2026.11.0")
explicit Rgb565ToMono(ColorOrder order) {
// Rec.601 weight of the 5-bit, 6-bit and 5-bit fields, by the channel each one holds in this order
uint16_t high = REC601_LUMA_R, middle = REC601_LUMA_G, low = REC601_LUMA_B;
if (order == COLOR_ORDER_BGR) {
high = REC601_LUMA_B;
low = REC601_LUMA_R;
} else if (order == COLOR_ORDER_GRB) {
high = REC601_LUMA_G;
middle = REC601_LUMA_R;
}
// Each field value scaled to 0..255, then weighted
for (unsigned i = 0; i != 32; i++) {
this->high_[i] = high * esp_scale(i, 31);
this->low_[i] = low * esp_scale(i, 31);
}
for (unsigned i = 0; i != 64; i++)
this->middle_[i] = middle * esp_scale(i, 63);
// The weight of the channel each 5, 6 and 5 bit field holds in this order
const Color weights = apply_color_order(Color(REC601_LUMA_R, REC601_LUMA_G, REC601_LUMA_B), order);
this->fill_tables_(weights.r, weights.g, weights.b);
}
uint8_t operator()(uint16_t value) const {
@@ -221,6 +235,16 @@ class Rgb565ToMono {
}
protected:
// Each field value scaled to 0..255, then weighted
void fill_tables_(uint16_t high, uint16_t middle, uint16_t low) {
for (unsigned i = 0; i != 32; i++) {
this->high_[i] = high * esp_scale(i, 31);
this->low_[i] = low * esp_scale(i, 31);
}
for (unsigned i = 0; i != 64; i++)
this->middle_[i] = middle * esp_scale(i, 63);
}
// Weighted contribution of each value of each field
std::array<uint16_t, 32> high_{};
std::array<uint16_t, 64> middle_{};
+15 -21
View File
@@ -9,13 +9,17 @@ ESPHOME_LOG_TAG(TAG, "dps310");
static constexpr uint32_t READ_RETRY_TIMEOUT_ID = 0;
void DPS310Component::setup() {
if (!this->setup_registers_())
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
}
bool DPS310Component::setup_registers_() {
uint8_t coef_data_raw[DPS310_NUM_COEF_REGS];
auto timer = DPS310_INIT_TIMEOUT;
uint8_t reg = 0;
// first, reset the sensor
if (!this->write_byte(DPS310_REG_RESET, DPS310_CMD_RESET)) {
this->mark_failed();
return;
return false;
}
delay(10);
// wait for the sensor and its coefficients to be ready
@@ -25,40 +29,32 @@ void DPS310Component::setup() {
}
if (!(reg & DPS310_BIT_SENSOR_RDY) || !(reg & DPS310_BIT_COEF_RDY)) { // the flags were not set in time
this->mark_failed();
return;
return false;
}
// read device ID
if (!this->read_byte(DPS310_REG_PROD_REV_ID, &this->prod_rev_id_)) {
this->mark_failed();
return;
return false;
}
// read in coefficients used to calculate the compensated pressure and temperature values
if (!this->read_bytes(DPS310_REG_COEF, coef_data_raw, DPS310_NUM_COEF_REGS)) {
this->mark_failed();
return;
return false;
}
// read in coefficients source register, too -- we need this a few lines down
if (!this->read_byte(DPS310_REG_TMP_COEF_SRC, &reg)) {
this->mark_failed();
return;
return false;
}
// set up operational stuff
if (!this->write_byte(DPS310_REG_PRS_CFG, DPS310_VAL_PRS_CFG)) {
this->mark_failed();
return;
return false;
}
if (!this->write_byte(DPS310_REG_TMP_CFG, DPS310_VAL_TMP_CFG | (reg & DPS310_BIT_TMP_COEF_SRC))) {
this->mark_failed();
return;
return false;
}
if (!this->write_byte(DPS310_REG_CFG, DPS310_VAL_REG_CFG)) {
this->mark_failed();
return;
return false;
}
if (!this->write_byte(DPS310_REG_MEAS_CFG, 0x07)) { // enable background mode
this->mark_failed();
return;
return false;
}
this->c0_ = // we only ever use c0/2, so just divide by 2 here to save time later
@@ -82,6 +78,7 @@ void DPS310Component::setup() {
this->c20_ = int16_t(((uint16_t) coef_data_raw[12] << 8) | (uint16_t) coef_data_raw[13]);
this->c21_ = int16_t(((uint16_t) coef_data_raw[14] << 8) | (uint16_t) coef_data_raw[15]);
this->c30_ = int16_t(((uint16_t) coef_data_raw[16] << 8) | (uint16_t) coef_data_raw[17]);
return true;
}
void DPS310Component::dump_config() {
@@ -91,9 +88,6 @@ void DPS310Component::dump_config() {
" Revision ID: %u",
this->prod_rev_id_ & 0x0F, (this->prod_rev_id_ >> 4) & 0x0F);
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
LOG_UPDATE_INTERVAL(this);
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
LOG_SENSOR(" ", "Pressure", this->pressure_sensor_);
+2
View File
@@ -45,6 +45,8 @@ class DPS310Component final : public PollingComponent, public i2c::I2CDevice {
void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; }
protected:
/// Configure the sensor; false on a failure.
bool setup_registers_();
void read_();
void read_pressure_();
void read_temperature_();
+1 -4
View File
@@ -10,7 +10,7 @@ ESPHOME_LOG_TAG(TAG, "ds1307");
void DS1307Component::setup() {
if (!this->read_rtc_()) {
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
}
}
@@ -19,9 +19,6 @@ void DS1307Component::update() { this->read_time(); }
void DS1307Component::dump_config() {
ESP_LOGCONFIG(TAG, "DS1307:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
RealTimeClock::dump_config();
}
-4
View File
@@ -29,10 +29,6 @@ void DS3231Component::setup() {
void DS3231Component::dump_config() {
ESP_LOGCONFIG(TAG, "DS3231:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
return;
}
}
bool DS3231Component::read_temperature(float &out) {
+1 -4
View File
@@ -60,7 +60,7 @@ void Emc2101Component::setup() {
uint8_t chip_id = reg(EMC2101_REGISTER_WHOAMI).get();
if ((chip_id != EMC2101_CHIP_ID) && (chip_id != EMC2101_ALT_CHIP_ID)) {
ESP_LOGE(TAG, "Wrong chip ID %02X", chip_id);
this->mark_failed();
this->mark_failed(LOG_STR("Wrong chip ID"));
return;
}
@@ -90,9 +90,6 @@ void Emc2101Component::setup() {
void Emc2101Component::dump_config() {
ESP_LOGCONFIG(TAG, "Emc2101 component:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
ESP_LOGCONFIG(TAG, " Mode: %s", this->dac_mode_ ? LOG_STR_LITERAL("DAC") : LOG_STR_LITERAL("PWM"));
if (this->dac_mode_) {
ESP_LOGCONFIG(TAG, " DAC Conversion Rate: %X", this->dac_conversion_rate_);
+15 -49
View File
@@ -62,20 +62,17 @@ void ENS160Component::setup() {
// check part_id
uint16_t part_id;
if (!this->read_bytes(ENS160_REG_PART_ID, reinterpret_cast<uint8_t *>(&part_id), 2)) {
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (part_id != ENS160_PART_ID) {
this->error_code_ = INVALID_ID;
this->mark_failed();
this->mark_failed(LOG_STR("Sensor reported an invalid ID. Is this a ENS160?"));
return;
}
// set mode to reset
if (!this->write_byte(ENS160_REG_OPMODE, ENS160_OPMODE_RESET)) {
this->error_code_ = WRITE_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
delay(ENS160_BOOTING);
@@ -83,51 +80,44 @@ void ENS160Component::setup() {
// check status
uint8_t status_value;
if (!this->read_byte(ENS160_REG_DATA_STATUS, &status_value)) {
this->error_code_ = READ_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
this->validity_flag_ = static_cast<ValidityFlag>((ENS160_DATA_STATUS_VALIDITY & status_value) >> 2);
if (this->validity_flag_ == INVALID_OUTPUT) {
this->error_code_ = VALIDITY_INVALID;
this->mark_failed();
this->mark_failed(LOG_STR("Invalid Device Status - No valid output"));
return;
}
// set mode to idle
if (!this->write_byte(ENS160_REG_OPMODE, ENS160_OPMODE_IDLE)) {
this->error_code_ = WRITE_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
delay(ENS160_BOOTING);
// clear command
if (!this->write_byte(ENS160_REG_COMMAND, ENS160_COMMAND_NOP)) {
this->error_code_ = WRITE_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (!this->write_byte(ENS160_REG_COMMAND, ENS160_COMMAND_CLRGPR)) {
this->error_code_ = WRITE_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
delay(ENS160_BOOTING);
// read firmware version
if (!this->write_byte(ENS160_REG_COMMAND, ENS160_COMMAND_GET_APPVER)) {
this->error_code_ = WRITE_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
delay(ENS160_BOOTING);
uint8_t version_data[3];
if (!this->read_bytes(ENS160_REG_GPR_READ_4, version_data, 3)) {
this->error_code_ = READ_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
this->firmware_ver_major_ = version_data[0];
@@ -136,22 +126,19 @@ void ENS160Component::setup() {
// set mode to standard
if (!this->write_byte(ENS160_REG_OPMODE, ENS160_OPMODE_STD)) {
this->error_code_ = WRITE_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
// read opmode and check standard mode is achieved before finishing Setup
uint8_t op_mode;
if (!this->read_byte(ENS160_REG_OPMODE, &op_mode)) {
this->error_code_ = READ_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
if (op_mode != ENS160_OPMODE_STD) {
this->error_code_ = STD_OPMODE_FAILED;
this->mark_failed();
this->mark_failed(LOG_STR("Device failed to achieve Standard Operating Mode"));
return;
}
}
@@ -291,29 +278,8 @@ void ENS160Component::send_env_data_() {
void ENS160Component::dump_config() {
ESP_LOGCONFIG(TAG, "ENS160:");
switch (this->error_code_) {
case COMMUNICATION_FAILED:
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
break;
case READ_FAILED:
ESP_LOGE(TAG, "Error reading from register");
break;
case WRITE_FAILED:
ESP_LOGE(TAG, "Error writing to register");
break;
case INVALID_ID:
ESP_LOGE(TAG, "Sensor reported an invalid ID. Is this a ENS160?");
break;
case VALIDITY_INVALID:
ESP_LOGE(TAG, "Invalid Device Status - No valid output");
break;
case STD_OPMODE_FAILED:
ESP_LOGE(TAG, "Device failed to achieve Standard Operating Mode");
break;
case NONE:
ESP_LOGD(TAG, "Setup successful");
break;
if (!this->is_failed()) {
ESP_LOGD(TAG, "Setup successful");
}
ESP_LOGI(TAG, "Firmware Version: %d.%d.%d", this->firmware_ver_major_, this->firmware_ver_minor_,
this->firmware_ver_build_);
@@ -21,16 +21,6 @@ class ENS160Component : public PollingComponent, public sensor::Sensor {
protected:
void send_env_data_();
enum ErrorCode {
NONE = 0,
COMMUNICATION_FAILED,
INVALID_ID,
VALIDITY_INVALID,
READ_FAILED,
WRITE_FAILED,
STD_OPMODE_FAILED,
} error_code_{NONE};
enum ValidityFlag {
NORMAL_OPERATION = 0,
WARMING_UP,
+7 -13
View File
@@ -55,8 +55,6 @@ static const LogString *ens210_status_to_human(int status) {
return LOG_STR("Invalid data");
case ENS210Component::ENS210_STATUS_OK:
return LOG_STR("Status OK");
case ENS210Component::ENS210_WRONG_CHIP_ID:
return LOG_STR("ENS210 has wrong chip ID! Is it a ENS210?");
default:
return LOG_STR("Unknown");
}
@@ -93,8 +91,7 @@ void ENS210Component::setup() {
// Reset
if (!this->write_byte(ENS210_REGISTER_SYS_CTRL, 0x80)) {
this->write_byte(ENS210_REGISTER_SYS_CTRL, 0x80);
this->error_code_ = ENS210_STATUS_I2C_ERROR;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
// Wait to boot after reset
@@ -103,24 +100,24 @@ void ENS210Component::setup() {
if (!set_low_power_(false)) {
// Try to go back to default mode (low power enabled)
set_low_power_(true);
this->error_code_ = ENS210_STATUS_I2C_ERROR;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
// Read the PART_ID
if (!this->read_bytes(ENS210_REGISTER_PART_ID, data, 2)) {
// Try to go back to default mode (low power enabled)
set_low_power_(true);
this->error_code_ = ENS210_STATUS_I2C_ERROR;
this->mark_failed();
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
return;
}
// Pack bytes into partid
part_id = data[1] * 256U + data[0] * 1U;
// Check expected part id of the ENS210
if (part_id != ENS210_PART_ID) {
this->error_code_ = ENS210_WRONG_CHIP_ID;
this->mark_failed();
// Try to go back to default mode (low power enabled)
set_low_power_(true);
this->mark_failed(LOG_STR("Wrong chip ID"));
return;
}
// Set default power mode (low power enabled)
set_low_power_(true);
@@ -129,9 +126,6 @@ void ENS210Component::setup() {
void ENS210Component::dump_config() {
ESP_LOGCONFIG(TAG, "ENS210:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, "%s", LOG_STR_ARG(ens210_status_to_human(this->error_code_)));
}
LOG_UPDATE_INTERVAL(this);
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
+1 -2
View File
@@ -22,8 +22,7 @@ class ENS210Component final : public PollingComponent, public i2c::I2CDevice {
// not yet finished)
ENS210_STATUS_CRC_ERROR, // The value was read, but the CRC over the payload (valid and data) does not match
ENS210_STATUS_I2C_ERROR, // There was an I2C communication error
ENS210_WRONG_CHIP_ID // The read PART_ID is not the expected part id of the ENS210
} error_code_{ENS210_STATUS_OK};
};
protected:
bool set_low_power_(bool enable);
+7 -6
View File
@@ -399,7 +399,7 @@ void HOT write_rgb565_row(uint8_t *byte, uint8_t mask, int step, size_t row_widt
// Each source column maps to one buffer coordinate and each source row to the other, each moving by 1 per pixel, so
// the visible part of a block and its dirty area are worked out once for the whole block.
void HOT EPaperBase::draw_rgb565_block_(uint8_t *buffer, int x_start, int y_start, int w, int h, const uint8_t *ptr,
ColorOrder order, bool big_endian, int x_offset, int y_offset, int x_pad) {
bool big_endian, int x_offset, int y_offset, int x_pad) {
const bool swap = this->effective_transform_ & SWAP_XY;
const bool mirror_x = this->effective_transform_ & MIRROR_X;
const bool mirror_y = this->effective_transform_ & MIRROR_Y;
@@ -432,7 +432,7 @@ void HOT EPaperBase::draw_rgb565_block_(uint8_t *buffer, int x_start, int y_star
const int x_high = x_low + (swap ? rows : columns);
const int y_high = y_low + (swap ? columns : rows);
const Rgb565ToMono to_mono(order);
const Rgb565ToMono to_mono;
const size_t line_stride = x_offset + w + x_pad;
const size_t row_width = this->row_width_;
const int step = column_mirrored ? -1 : 1;
@@ -464,16 +464,17 @@ void HOT EPaperBase::draw_rgb565_block_(uint8_t *buffer, int x_start, int y_star
// Writes an RGB565 block of pixels, as LVGL sends them, straight into a 1 bit per pixel buffer that is one block (the
// usual case): the same result as draw_pixel_at() for each pixel. Anything else goes through draw_pixel_at().
void HOT EPaperBase::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) {
void HOT EPaperBase::draw_pixels_internal(int x_start, int y_start, int w, int h, const uint8_t *ptr,
ColorBitness bitness, bool big_endian, int x_offset, int y_offset,
int x_pad) {
size_t contiguous_length;
uint8_t *contiguous = this->buffer_.get_span(0, contiguous_length);
if (!this->buffer_is_mono_() || this->get_clipping().is_set() || bitness != COLOR_BITNESS_565 ||
contiguous_length != this->buffer_length_) {
Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad);
Display::draw_pixels_internal(x_start, y_start, w, h, ptr, bitness, big_endian, x_offset, y_offset, x_pad);
return;
}
this->draw_rgb565_block_(contiguous, x_start, y_start, w, h, ptr, order, big_endian, x_offset, y_offset, x_pad);
this->draw_rgb565_block_(contiguous, x_start, y_start, w, h, ptr, big_endian, x_offset, y_offset, x_pad);
}
void EPaperBase::dump_config() {
+5 -4
View File
@@ -111,14 +111,15 @@ class EPaperBase : public Display,
int get_height() override { return this->effective_transform_ & SWAP_XY ? this->width_ : this->height_; }
bool pixel_axes_swapped() const override { return this->effective_transform_ & SWAP_XY; }
void draw_pixel_at(int x, int y, Color color) override;
void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) override;
// Make the next update a full one. Applied when that update starts, so one in progress is not affected.
void request_full_update() { this->full_update_requested_ = true; }
// True from the start of an update until the display has refreshed and gone back to sleep.
bool is_updating() const { return this->state_ != EPaperState::IDLE; }
protected:
void draw_pixels_internal(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorBitness bitness,
bool big_endian, int x_offset, int y_offset, int x_pad) override;
int get_height_internal() override { return this->height_; };
int get_width_internal() override { return this->width_; };
bool is_using_partial_update_() const { return this->full_update_every_ > 1; }
@@ -135,8 +136,8 @@ class EPaperBase : public Display,
bool init_buffer_(size_t buffer_length);
void update_effective_transform_();
bool rotate_coordinates_(int &x, int &y);
void draw_rgb565_block_(uint8_t *buffer, int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
bool big_endian, int x_offset, int y_offset, int x_pad);
void draw_rgb565_block_(uint8_t *buffer, int x_start, int y_start, int w, int h, const uint8_t *ptr, bool big_endian,
int x_offset, int y_offset, int x_pad);
// Whether the buffer is a single plane of 1 bit per pixel, as draw_pixel_at() writes it
bool buffer_is_mono_() const { return this->bits_per_pixel_ == 1 && this->planes_ == 1; }
+1 -6
View File
@@ -13,7 +13,7 @@ static const size_t MCLK_DIV_FRE = 256;
// Mark the component as failed; use only in setup
#define ES7210_ERROR_FAILED(func) \
if (!(func)) { \
this->mark_failed(); \
this->mark_failed(LOG_STR("Failed to initialize")); \
return; \
}
@@ -31,11 +31,6 @@ void ES7210::dump_config() {
" Channel Gains: %.1f dB, %.1f dB, %.1f dB, %.1f dB",
this->bits_per_sample_, this->sample_rate_, this->channel_gains_[0], this->channel_gains_[1],
this->channel_gains_[2], this->channel_gains_[3]);
if (this->is_failed()) {
ESP_LOGE(TAG, " Failed to initialize");
return;
}
}
void ES7210::setup() {
+2 -9
View File
@@ -13,7 +13,7 @@ ESPHOME_LOG_TAG(TAG, "es7243e");
// Mark the component as failed; use only in setup
#define ES7243E_ERROR_FAILED(func) \
if (!(func)) { \
this->mark_failed(); \
this->mark_failed(LOG_STR("Failed to initialize")); \
return; \
}
@@ -23,14 +23,7 @@ ESPHOME_LOG_TAG(TAG, "es7243e");
return false; \
}
void ES7243E::dump_config() {
ESP_LOGCONFIG(TAG, "ES7243E audio ADC:");
if (this->is_failed()) {
ESP_LOGE(TAG, " Failed to initialize");
return;
}
}
void ES7243E::dump_config() { ESP_LOGCONFIG(TAG, "ES7243E audio ADC:"); }
void ES7243E::setup() {
ES7243E_ERROR_FAILED(this->write_byte(ES7243E_CLOCK_MGR_REG01, 0x3A));
+2 -9
View File
@@ -11,7 +11,7 @@ ESPHOME_LOG_TAG(TAG, "es8156");
// Mark the component as failed; use only in setup
#define ES8156_ERROR_FAILED(func) \
if (!(func)) { \
this->mark_failed(); \
this->mark_failed(LOG_STR("Failed to initialize")); \
return; \
}
@@ -74,14 +74,7 @@ void ES8156::setup() {
ES8156_ERROR_FAILED(this->write_byte(ES8156_REG25_ANALOG_SYS5, 0x20));
}
void ES8156::dump_config() {
ESP_LOGCONFIG(TAG, "ES8156 Audio Codec:");
if (this->is_failed()) {
ESP_LOGCONFIG(TAG, " Failed to initialize");
return;
}
}
void ES8156::dump_config() { ESP_LOGCONFIG(TAG, "ES8156 Audio Codec:"); }
bool ES8156::set_volume(float volume) {
volume = clamp(volume, 0.0f, 1.0f);
+1 -6
View File
@@ -11,7 +11,7 @@ ESPHOME_LOG_TAG(TAG, "es8311");
// Mark the component as failed; use only in setup
#define ES8311_ERROR_FAILED(func) \
if (!(func)) { \
this->mark_failed(); \
this->mark_failed(LOG_STR("Failed to initialize")); \
return; \
}
// Return false; use outside of setup
@@ -56,11 +56,6 @@ void ES8311::dump_config() {
" DAC Bits per Sample: %" PRIu8 "\n"
" Sample Rate: %" PRIu32,
YESNO(this->use_mclk_), YESNO(this->use_mic_), this->resolution_out_, this->sample_frequency_);
if (this->is_failed()) {
ESP_LOGCONFIG(TAG, " Failed to initialize!");
return;
}
}
bool ES8311::set_volume(float volume) {
+1 -6
View File
@@ -11,7 +11,7 @@ ESPHOME_LOG_TAG(TAG, "es8388");
// Mark the component as failed; use only in setup
#define ES8388_ERROR_FAILED(func) \
if (!(func)) { \
this->mark_failed(); \
this->mark_failed(LOG_STR("Failed to initialize")); \
return; \
}
@@ -154,11 +154,6 @@ void ES8388::dump_config() {
LOG_SELECT(" ", "DacOutputSelect", this->dac_output_select_);
LOG_SELECT(" ", "ADCInputMicSelect", this->adc_input_mic_select_);
#endif
if (this->is_failed()) {
ESP_LOGCONFIG(TAG, " Failed to initialize");
return;
}
}
bool ES8388::set_volume(float volume) {
+9 -5
View File
@@ -28,14 +28,12 @@ ADC_INPUT_MIC_OPTIONS = {
}
ADC_INPUT_MIC_OPTION_NAMES = list(ADC_INPUT_MIC_OPTIONS)
DacOutputSelect = es8388_ns.class_("DacOutputSelect", select.Select)
ADCInputMicSelect = es8388_ns.class_("ADCInputMicSelect", select.Select)
CONFIG_SCHEMA = cv.All(
{
cv.GenerateID(CONF_ES8388_ID): cv.use_id(ES8388),
cv.Optional(CONF_DAC_OUTPUT): select.select_schema(
DacOutputSelect,
select.ApplySelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_CHIP,
).extend(
@@ -46,7 +44,7 @@ CONFIG_SCHEMA = cv.All(
}
),
cv.Optional(CONF_ADC_INPUT_MIC): select.select_schema(
ADCInputMicSelect,
select.ApplySelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon=ICON_CHIP,
).extend(
@@ -65,12 +63,18 @@ async def to_code(config: ConfigType) -> None:
hub = await cg.get_variable(config[CONF_ES8388_ID])
selects = select.sub_selects(config, parent=hub)
await selects(
CONF_DAC_OUTPUT, hub.set_dac_output_select, options=DAC_OUTPUT_OPTION_NAMES
CONF_DAC_OUTPUT,
hub.set_dac_output_select,
options=DAC_OUTPUT_OPTION_NAMES,
apply="set_dac_output(static_cast<es8388::DacOutputLine>(index))",
publish="before",
)
await selects(
CONF_ADC_INPUT_MIC,
hub.set_adc_input_mic_select,
options=ADC_INPUT_MIC_OPTION_NAMES,
apply="set_adc_input_mic(static_cast<es8388::AdcInputMicLine>(index))",
publish="before",
)
if (
initial := config.get(CONF_DAC_OUTPUT, {}).get(CONF_INITIAL_OPTION)
@@ -1,10 +0,0 @@
#include "adc_input_mic_select.h"
namespace esphome::es8388 {
void ADCInputMicSelect::control(size_t index) {
this->publish_state(index);
this->parent_->set_adc_input_mic(static_cast<AdcInputMicLine>(index));
}
} // namespace esphome::es8388
@@ -1,13 +0,0 @@
#pragma once
#include "esphome/components/es8388/es8388.h"
#include "esphome/components/select/select.h"
namespace esphome::es8388 {
class ADCInputMicSelect final : public select::Select, public Parented<ES8388> {
protected:
void control(size_t index) override;
};
} // namespace esphome::es8388
@@ -1,10 +0,0 @@
#include "dac_output_select.h"
namespace esphome::es8388 {
void DacOutputSelect::control(size_t index) {
this->publish_state(index);
this->parent_->set_dac_output(static_cast<DacOutputLine>(index));
}
} // namespace esphome::es8388
@@ -1,13 +0,0 @@
#pragma once
#include "esphome/components/es8388/es8388.h"
#include "esphome/components/select/select.h"
namespace esphome::es8388 {
class DacOutputSelect final : public select::Select, public Parented<ES8388> {
protected:
void control(size_t index) override;
};
} // namespace esphome::es8388
@@ -42,7 +42,7 @@ CameraWebServer::~CameraWebServer() {}
void CameraWebServer::setup() {
if (!camera::Camera::instance() || camera::Camera::instance()->is_failed()) {
this->mark_failed();
this->mark_failed(LOG_STR("Camera not available"));
return;
}
@@ -56,7 +56,7 @@ void CameraWebServer::setup() {
config.lru_purge_enable = true;
if (httpd_start(&this->httpd_, &config) != ESP_OK) {
mark_failed();
this->mark_failed(LOG_STR("Failed to start the web server"));
return;
}
@@ -97,10 +97,6 @@ void CameraWebServer::dump_config() {
} else {
ESP_LOGCONFIG(TAG, " Mode: snapshot");
}
if (this->is_failed()) {
ESP_LOGE(TAG, " Setup Failed");
}
}
float CameraWebServer::get_setup_priority() const { return setup_priority::LATE; }
@@ -1,20 +1,18 @@
import esphome.codegen as cg
from esphome.components import button
import esphome.config_validation as cv
from esphome.const import ENTITY_CATEGORY_CONFIG
from esphome.types import ConfigType
from .. import CONF_ESPECTRE_ID, ESPectreComponent, espectre_ns
from .. import CONF_ESPECTRE_ID, ESPectreComponent
DEPENDENCIES = ["espectre"]
RecalibrateButton = espectre_ns.class_("RecalibrateButton", button.Button)
CONFIG_SCHEMA = button.button_schema(
RecalibrateButton, entity_category=ENTITY_CATEGORY_CONFIG
button.ApplyButton, entity_category=ENTITY_CATEGORY_CONFIG
).extend({cv.GenerateID(CONF_ESPECTRE_ID): cv.use_id(ESPectreComponent)})
async def to_code(config: ConfigType) -> None:
var = await button.new_button(config)
await cg.register_parented(var, config[CONF_ESPECTRE_ID])
buttons = button.sub_buttons(config, parent=config[CONF_ESPECTRE_ID])
await buttons.create(config, None, apply="recalibrate()")
@@ -1,19 +0,0 @@
#pragma once
#include "esphome/core/defines.h"
#ifdef USE_ESPECTRE
#include "esphome/components/button/button.h"
#include "../espectre.h"
namespace esphome::espectre {
class RecalibrateButton final : public button::Button, public Parented<ESPectreComponent> {
protected:
void press_action() override { this->parent_->recalibrate(); }
};
} // namespace esphome::espectre
#endif // USE_ESPECTRE
@@ -9,24 +9,23 @@ from .. import (
CONF_ESPECTRE_ID,
DOMAIN,
ESPectreComponent,
espectre_ns,
supported_traffic_generator_modes,
)
DEPENDENCIES = ["espectre"]
TrafficModeSelect = espectre_ns.class_(
"TrafficModeSelect", select.Select, cg.Parented.template(ESPectreComponent)
)
CONFIG_SCHEMA = select.select_schema(
TrafficModeSelect, entity_category=ENTITY_CATEGORY_CONFIG
select.ApplySelect, entity_category=ENTITY_CATEGORY_CONFIG
).extend({cv.GenerateID(CONF_ESPECTRE_ID): cv.use_id(ESPectreComponent)})
async def to_code(config: ConfigType) -> None:
options = supported_traffic_generator_modes(CORE.config[DOMAIN])
var = await select.new_select(config, options=options)
await cg.register_parented(var, config[CONF_ESPECTRE_ID])
parent = await cg.get_variable(config[CONF_ESPECTRE_ID])
cg.add(parent.set_traffic_mode_select(var))
hub = await cg.get_variable(config[CONF_ESPECTRE_ID])
await select.sub_selects(config, parent=hub).create(
config,
hub.set_traffic_mode_select,
options=options,
apply="request_traffic_generator_mode(entity->option_at(index))",
)
@@ -1,11 +0,0 @@
#include "espectre_select.h"
#ifdef USE_ESPECTRE
namespace esphome::espectre {
void TrafficModeSelect::control(size_t index) { this->parent_->request_traffic_generator_mode(this->option_at(index)); }
} // namespace esphome::espectre
#endif // USE_ESPECTRE
@@ -1,19 +0,0 @@
#pragma once
#include "esphome/core/defines.h"
#ifdef USE_ESPECTRE
#include "esphome/components/select/select.h"
#include "../espectre.h"
namespace esphome::espectre {
class TrafficModeSelect final : public select::Select, public Parented<ESPectreComponent> {
protected:
void control(size_t index) override;
};
} // namespace esphome::espectre
#endif // USE_ESPECTRE
-3
View File
@@ -13,9 +13,6 @@ static const char *const EZO_CALIBRATION_TYPE_STRINGS[] = {"LOW", "MID", "HIGH"}
void EZOSensor::dump_config() {
LOG_SENSOR("", "EZO", this);
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
LOG_UPDATE_INTERVAL(this);
}
-3
View File
@@ -39,9 +39,6 @@ static const std::string DOSING_MODE_CONTINUOUS = "Continuous";
void EzoPMP::dump_config() {
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
LOG_UPDATE_INTERVAL(this);
}
+7 -1
View File
@@ -254,7 +254,13 @@ async def new_image(config: ConfigType) -> MockObj:
"""
prog_arr, width, height, image_type, trans_value, _ = await write_image(config)
var = cg.new_Pvariable(
config[CONF_ID], prog_arr, width, height, image_type, trans_value
config[CONF_ID],
prog_arr,
width,
height,
image_type,
trans_value,
config.get(CONF_BYTE_ORDER) == "BIG_ENDIAN",
)
add_metadata(
config[CONF_ID], width, height, config[CONF_TYPE], config[CONF_TRANSPARENCY]
-3
View File
@@ -82,9 +82,6 @@ bool GDK101Component::try_reset_() {
void GDK101Component::dump_config() {
ESP_LOGCONFIG(TAG, "GDK101:");
LOG_I2C_DEVICE(this);
if (this->is_failed()) {
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
}
#ifdef USE_SENSOR
LOG_SENSOR(" ", "Average Radaition Dose per 1 minute", this->rad_1m_sensor_);
LOG_SENSOR(" ", "Average Radaition Dose per 10 minutes", this->rad_10m_sensor_);
@@ -23,7 +23,6 @@ bool GroveGasMultichannelV2Component::read_sensor_(uint8_t address, sensor::Sens
uint32_t value = 0;
if (!this->read_bytes(address, (uint8_t *) &value, 4)) {
ESP_LOGW(TAG, "Reading Grove Gas Sensor data failed!");
this->error_code_ = COMMUNICATION_FAILED;
this->status_set_warning();
return false;
}
@@ -34,8 +33,7 @@ bool GroveGasMultichannelV2Component::read_sensor_(uint8_t address, sensor::Sens
void GroveGasMultichannelV2Component::setup() {
// Before reading sensor values, must preheat sensor
if (!(this->write_bytes(GROVE_GAS_MC_V2_HEAT_ON, {}))) {
this->mark_failed();
this->error_code_ = APP_START_FAILED;
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
}
}
@@ -61,24 +59,6 @@ void GroveGasMultichannelV2Component::dump_config() {
LOG_SENSOR(" ", "Ethanol", this->ethanol_sensor_);
LOG_SENSOR(" ", "Carbon Monoxide", this->carbon_monoxide_sensor_);
LOG_SENSOR(" ", "TVOC", this->tvoc_sensor_);
if (this->is_failed()) {
switch (this->error_code_) {
case COMMUNICATION_FAILED:
ESP_LOGW(TAG, ESP_LOG_MSG_COMM_FAIL);
break;
case APP_INVALID:
ESP_LOGW(TAG, "Sensor reported invalid APP installed");
break;
case APP_START_FAILED:
ESP_LOGW(TAG, "Sensor reported APP start failed");
break;
case UNKNOWN:
default:
ESP_LOGW(TAG, "Unknown setup error");
break;
}
}
}
} // namespace esphome::grove_gas_mc_v2
Loaded 100 of 462 files, more files were not shown because too many files have changed in this diff. Show more