Compare commits

...
Author SHA1 Message Date
J. Nick Koston 49b1a67509 Give the host platform a no-op InterruptLock
Components that take an InterruptLock around bit-banged I/O could not be
compiled or unit tested on the host because it never defined the class.
2026-10-16 16:52:30 -10:00
J. Nick Koston a5a883fd19 [core] Add xor_bytes and sum16_bytes checksum helpers (#20921) 2026-10-16 15:57:00 -10:00
J. Nick Koston 7671d4410c [i2c] Add check_chip_id helper (#20941) 2026-10-16 15:55:53 -10:00
J. Nick Koston 298bd5ec72 [core] Add ESP_LOGV_HEX, ESP_LOGVV_HEX and ESP_LOGD_HEX (#20931) 2026-10-16 15:55:28 -10:00
J. Nick Koston b8afcdfb3c [i2c] Write 16-bit registers without a heap allocation (#20907) 2026-10-16 15:54:53 -10:00
luar123andJ. Nick Koston 9031df757b [core][scheduler] add missing process_to_add call (#20961)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-17 01:33:29 +00:00
J. Nick Koston 107bebebad [components] Use sign_extend for raw sensor readings (#20934) 2026-10-16 15:24:45 -10:00
J. Nick Koston 1147b024d6 [core] Add sign_extend helper (#20933) 2026-10-16 21:17:59 -04:00
J. Nick Koston 36ba2f6106 [components] Build enum option dicts with options() (#20911) 2026-10-16 14:56:34 -10:00
J. Nick Koston bb0eabf241 [core] Add options() to C++ enums (#20910) 2026-10-16 14:56:34 -10:00
Frédéric MetrichandClaude d9969dd533 [teleinfo] Skip sensor values that are not numbers instead of publishing 0 (#20960)
Co-authored-by: Claude <noreply@anthropic.com>
2026-10-16 14:55:08 -10:00
Clyde Stubbs 51ae3bb642 [ci] Rename merge conflict label to has-conflicts (#20969) 2026-10-16 14:31:06 -10:00
b3ef5cf2f3 [online_image] Report an error when a download can never complete (#20594)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: guillempages <guillempages@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-10-16 23:58:12 +00:00
Hasan Khalil b3f5789dc6 [mipi_rgb] direct-to-PSRAM fast rotated blitting (#20905) 2026-10-17 10:39:44 +11:00
J. Nick Koston 1ddacb4931 [tests] Set i2c_id in the component tests that clash with tca9548a (#20963) 2026-10-16 13:24:34 -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
Kevin Ahrendt 6817960365 [audio] Deprecate AudioSourceTransferBuffer (#20801) 2026-10-15 13:38:03 -10:00
Kevin Ahrendt cfdaf958e9 [audio][i2s_audio] Fix 16-bit mono playback at 44.1 kHz on the original ESP32 (#20806) 2026-10-15 13:32:35 -10:00
480 changed files with 8119 additions and 3477 deletions
+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
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
days-before-close: 7
stale-label: stale
exempt-label: not-stale
conflict-label: needs-rebase
conflict-label: has-conflicts
ignored-users: esphbot,codecov-commenter
stale-pr-message: >
There hasn't been any activity on this pull request recently. This
+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 \
@@ -19,11 +19,7 @@ AbsoluteHumidityComponent = absolute_humidity_ns.class_(
SaturationVaporPressureEquation = absolute_humidity_ns.enum(
"SaturationVaporPressureEquation"
)
EQUATION = {
"BUCK": SaturationVaporPressureEquation.BUCK,
"TETENS": SaturationVaporPressureEquation.TETENS,
"WOBUS": SaturationVaporPressureEquation.WOBUS,
}
EQUATION = SaturationVaporPressureEquation.options("BUCK", "TETENS", "WOBUS")
CONFIG_SCHEMA = (
sensor.sensor_schema(
+3 -5
View File
@@ -14,11 +14,9 @@ ac_dimmer_ns = cg.esphome_ns.namespace("ac_dimmer")
AcDimmer = ac_dimmer_ns.class_("AcDimmer", output.FloatOutput, cg.Component)
DimMethod = ac_dimmer_ns.enum("DimMethod")
DIM_METHODS = {
"LEADING_PULSE": DimMethod.DIM_METHOD_LEADING_PULSE,
"LEADING": DimMethod.DIM_METHOD_LEADING,
"TRAILING": DimMethod.DIM_METHOD_TRAILING,
}
DIM_METHODS = DimMethod.options(
"LEADING_PULSE", "LEADING", "TRAILING", prefix="DIM_METHOD_"
)
ZC_INTERRUPT_TYPES = {
"RISING": gpio_ns.INTERRUPT_RISING_EDGE,
+1 -5
View File
@@ -46,11 +46,7 @@ ATTENUATION_MODES = {
sampling_mode = adc_ns.enum("SamplingMode", is_class=True)
SAMPLING_MODES = {
"avg": sampling_mode.AVG,
"min": sampling_mode.MIN,
"max": sampling_mode.MAX,
}
SAMPLING_MODES = sampling_mode.options("avg", "min", "max")
adc_unit_t = cg.global_ns.enum("adc_unit_t", is_class=True)
+1 -7
View File
@@ -11,12 +11,6 @@
namespace esphome::ade7880 {
// adapted from https://stackoverflow.com/a/55912127/1886371
template<size_t Bits, typename T> inline T sign_extend(const T &v) noexcept {
using S = struct { signed Val : Bits; };
return reinterpret_cast<const S *>(&v)->Val;
}
// Register types
// unsigned 8-bit (uint8_t)
// signed 10-bit - 16-bit ZP on wire (int16_t, needs sign extension)
@@ -49,7 +43,7 @@ uint16_t ADE7880::read_u16_register16_(uint16_t a_register) {
int32_t ADE7880::read_s24zp_register16_(uint16_t a_register) {
// s24zp means 24 bit signed value in the lower 24 bits of a 32-bit register
int32_t in;
uint32_t in;
this->read_register16(a_register, reinterpret_cast<uint8_t *>(&in), sizeof(in));
return sign_extend<24>(convert_big_endian(in));
}
+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) {
+3 -5
View File
@@ -84,11 +84,9 @@ automation.register_apply_action(
)
AGS10SetZeroPointActionMode = ags10_ns.enum("AGS10SetZeroPointActionMode")
AGS10_SET_ZERO_POINT_ACTION_MODE = {
"FACTORY_DEFAULT": AGS10SetZeroPointActionMode.FACTORY_DEFAULT,
"CURRENT_VALUE": AGS10SetZeroPointActionMode.CURRENT_VALUE,
"CUSTOM_VALUE": AGS10SetZeroPointActionMode.CUSTOM_VALUE,
}
AGS10_SET_ZERO_POINT_ACTION_MODE = AGS10SetZeroPointActionMode.options(
"FACTORY_DEFAULT", "CURRENT_VALUE", "CUSTOM_VALUE"
)
AGS10_SET_ZERO_POINT_SCHEMA = cv.Schema(
{
+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 -4
View File
@@ -20,10 +20,7 @@ aht10_ns = cg.esphome_ns.namespace("aht10")
AHT10Component = aht10_ns.class_("AHT10Component", cg.PollingComponent, i2c.I2CDevice)
AHT10Variant = aht10_ns.enum("AHT10Variant")
AHT10_VARIANTS = {
"AHT10": AHT10Variant.AHT10,
"AHT20": AHT10Variant.AHT20,
}
AHT10_VARIANTS = AHT10Variant.options("AHT10", "AHT20")
CONFIG_SCHEMA = (
cv.Schema(
+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() {
@@ -29,10 +29,7 @@ AirthingsWavePlus = airthings_wave_plus_ns.class_(
CONF_DEVICE_TYPE = "device_type"
WaveDeviceType = airthings_wave_plus_ns.enum("WaveDeviceType")
DEVICE_TYPES = {
"WAVE_PLUS": WaveDeviceType.WAVE_PLUS,
"WAVE_GEN2": WaveDeviceType.WAVE_GEN2,
}
DEVICE_TYPES = WaveDeviceType.options("WAVE_PLUS", "WAVE_GEN2")
def validate_wave_gen2_config(config: ConfigType) -> ConfigType:
+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"
+1 -4
View File
@@ -30,10 +30,7 @@ CONF_END_POSITION = "end_position"
CONF_OUT_OF_RANGE_MODE = "out_of_range_mode"
OutOfRangeMode = as5600_ns.enum("OutRangeMode")
OUT_OF_RANGE_MODES = {
"MIN_MAX": OutOfRangeMode.OUT_RANGE_MODE_MIN_MAX,
"NAN": OutOfRangeMode.OUT_RANGE_MODE_NAN,
}
OUT_OF_RANGE_MODES = OutOfRangeMode.options("MIN_MAX", "NAN", prefix="OUT_RANGE_MODE_")
CONF_AS5600_ID = "as5600_id"
+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 -6
View File
@@ -55,12 +55,9 @@ GAINS_41 = {
GAINS_43 = {**GAINS_41, "X1024": Gain.GAIN_1024X, "X2048": Gain.GAIN_2048X}
Normalization = as734x_ns.enum("Normalization", True)
NORMALIZATIONS = {
"NONE": Normalization.NORMALIZATION_NONE,
"ALL": Normalization.NORMALIZATION_ALL,
"BANDS": Normalization.NORMALIZATION_BANDS,
"CLEAR": Normalization.NORMALIZATION_CLEAR,
}
NORMALIZATIONS = Normalization.options(
"NONE", "ALL", "BANDS", "CLEAR", prefix="NORMALIZATION_"
)
# Per-channel correction for the golden device, measured by the manufacturer.
DEFAULT_CHANNEL_CORRECTION_43 = [
-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(
+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 -7
View File
@@ -27,13 +27,7 @@ audio_ns = cg.esphome_ns.namespace("audio")
AudioFile = audio_ns.struct("AudioFile")
AudioFileType = audio_ns.enum("AudioFileType", is_class=True)
AUDIO_FILE_TYPE_ENUM = {
"NONE": AudioFileType.NONE,
"WAV": AudioFileType.WAV,
"MP3": AudioFileType.MP3,
"FLAC": AudioFileType.FLAC,
"OPUS": AudioFileType.OPUS,
}
AUDIO_FILE_TYPE_ENUM = AudioFileType.options("NONE", "WAV", "MP3", "FLAC", "OPUS")
MEMORY_PSRAM = "psram"
MEMORY_INTERNAL = "internal"
+1 -1
View File
@@ -188,7 +188,7 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) {
// Expose the next chunk of file data. Every decoder buffers internally and consumes only what it
// processed, so the source does not need to accumulate or stitch chunks across fill() calls.
this->input_buffer_->fill(pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS), false);
this->input_buffer_->fill(pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS));
const size_t available_before_decode = this->input_buffer_->available();
+2 -3
View File
@@ -129,9 +129,8 @@ AudioResamplerState AudioResampler::resample(bool stop_gracefully, int32_t *ms_d
delay(READ_WRITE_TIMEOUT_MS);
}
// Expose a chunk of the ring buffer's internal storage. pre_shift is ignored by RingBufferAudioSource
// (there is no intermediate transfer buffer to compact).
this->audio_source_->fill(pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS), false);
// Expose a chunk of the ring buffer's internal storage.
this->audio_source_->fill(pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS));
if (this->audio_source_->available() == 0) {
// No samples available to process
@@ -20,16 +20,6 @@ std::unique_ptr<AudioSinkTransferBuffer> AudioSinkTransferBuffer::create(size_t
return sink_buffer;
}
std::unique_ptr<AudioSourceTransferBuffer> AudioSourceTransferBuffer::create(size_t buffer_size) {
std::unique_ptr<AudioSourceTransferBuffer> source_buffer = make_unique<AudioSourceTransferBuffer>();
if (!source_buffer->allocate_buffer_(buffer_size)) {
return nullptr;
}
return source_buffer;
}
size_t AudioTransferBuffer::free() const {
if (this->buffer_size_ == 0) {
return 0;
@@ -132,27 +122,6 @@ void AudioTransferBuffer::deallocate_buffer_() {
this->buffer_length_ = 0;
}
size_t AudioSourceTransferBuffer::transfer_data_from_source(TickType_t ticks_to_wait, bool pre_shift) {
if (pre_shift) {
// Shift data in buffer to start
if (this->buffer_length_ > 0) {
std::memmove(this->buffer_, this->data_start_, this->buffer_length_);
}
this->data_start_ = this->buffer_;
}
size_t bytes_to_read = AudioTransferBuffer::free();
size_t bytes_read = 0;
if (bytes_to_read > 0) {
if (this->ring_buffer_ != nullptr) {
bytes_read = this->ring_buffer_->read((void *) this->get_buffer_end(), bytes_to_read, ticks_to_wait);
}
this->increase_buffer_length(bytes_read);
}
return bytes_read;
}
size_t AudioSinkTransferBuffer::transfer_data_to_sink(TickType_t ticks_to_wait, bool post_shift) {
size_t bytes_written = 0;
if (this->available()) {
@@ -192,9 +161,44 @@ bool AudioSinkTransferBuffer::has_buffered_data() const {
return (this->available() > 0);
}
// AudioSourceTransferBuffer is deprecated. Remove before 2027.5.0.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
std::unique_ptr<AudioSourceTransferBuffer> AudioSourceTransferBuffer::create(size_t buffer_size) {
std::unique_ptr<AudioSourceTransferBuffer> source_buffer = make_unique<AudioSourceTransferBuffer>();
if (!source_buffer->allocate_buffer_(buffer_size)) {
return nullptr;
}
return source_buffer;
}
size_t AudioSourceTransferBuffer::transfer_data_from_source(TickType_t ticks_to_wait, bool pre_shift) {
if (pre_shift) {
// Shift data in buffer to start
if (this->buffer_length_ > 0) {
std::memmove(this->buffer_, this->data_start_, this->buffer_length_);
}
this->data_start_ = this->buffer_;
}
size_t bytes_to_read = AudioTransferBuffer::free();
size_t bytes_read = 0;
if (bytes_to_read > 0) {
if (this->ring_buffer_ != nullptr) {
bytes_read = this->ring_buffer_->read((void *) this->get_buffer_end(), bytes_to_read, ticks_to_wait);
}
this->increase_buffer_length(bytes_read);
}
return bytes_read;
}
size_t AudioSourceTransferBuffer::free() const { return AudioTransferBuffer::free(); }
bool AudioSourceTransferBuffer::has_buffered_data() const { return AudioTransferBuffer::has_buffered_data(); }
#pragma GCC diagnostic pop
void ConstAudioSourceBuffer::set_data(const uint8_t *data, size_t length) {
this->data_start_ = data;
@@ -268,6 +272,23 @@ void RingBufferAudioSource::clear_buffered_data() {
this->ring_buffer_->reset();
}
size_t RingBufferAudioSource::expose_padded_partial(size_t frame_bytes) {
if (this->current_available_ > 0 || this->queued_length_ > 0) {
return 0;
}
// Moves any trailing bytes still inside a held item into the splice buffer
this->release_item_();
const size_t real_bytes = this->splice_length_;
if (real_bytes == 0 || frame_bytes == 0 || real_bytes % frame_bytes != 0) {
return 0;
}
std::memset(this->splice_buffer_ + real_bytes, 0, this->alignment_bytes_ - real_bytes);
this->splice_length_ = 0;
this->current_data_ = this->splice_buffer_;
this->current_available_ = this->alignment_bytes_;
return real_bytes;
}
bool RingBufferAudioSource::has_buffered_data() const {
// splice_length_ is deliberately not considered here. It holds an incomplete frame whose completion
// bytes must still arrive through the ring buffer, which ring_buffer_->available() already reports.
@@ -276,7 +297,7 @@ bool RingBufferAudioSource::has_buffered_data() const {
return (this->current_available_ > 0) || (this->queued_length_ > 0) || (this->ring_buffer_->available() > 0);
}
size_t RingBufferAudioSource::fill(TickType_t ticks_to_wait, bool /*pre_shift*/) {
size_t RingBufferAudioSource::fill(TickType_t ticks_to_wait) {
if (this->current_available_ > 0) {
// Caller has not finished consuming the current exposure
return 0;
@@ -3,6 +3,7 @@
#ifdef USE_ESP32
#include "esphome/components/ring_buffer/ring_buffer.h"
#include "esphome/core/defines.h"
#include "esphome/core/helpers.h" // for ESPDEPRECATED
#ifdef USE_SPEAKER
#include "esphome/components/speaker/speaker.h"
@@ -152,13 +153,20 @@ class AudioReadableBuffer {
/// @brief Refills the buffer from its source. No-op by default for read-only buffers.
/// @param ticks_to_wait FreeRTOS ticks to block while waiting for data
/// @param pre_shift If true, shifts existing data to the start of the buffer before reading
/// @return Number of bytes read
virtual size_t fill(TickType_t ticks_to_wait, bool pre_shift) { return 0; }
size_t fill(TickType_t ticks_to_wait) { return this->fill(ticks_to_wait, true); }
virtual size_t fill(TickType_t ticks_to_wait) { return 0; }
// Remove before 2027.5.0
ESPDEPRECATED("Use fill(ticks_to_wait) instead. Removed in 2027.5.0.", "2026.11.0")
virtual size_t fill(TickType_t ticks_to_wait, bool pre_shift) { return this->fill(ticks_to_wait); }
};
class AudioSourceTransferBuffer : public AudioTransferBuffer, public AudioReadableBuffer {
// Remove before 2027.5.0
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
class ESPDEPRECATED("Use RingBufferAudioSource instead. Removed in 2027.5.0.", "2026.11.0") AudioSourceTransferBuffer
: public AudioTransferBuffer,
public AudioReadableBuffer {
/*
* @brief A class that implements a transfer buffer for audio sources.
* Supports reading audio data from a ring buffer into the transfer buffer for processing.
@@ -189,10 +197,12 @@ class AudioSourceTransferBuffer : public AudioTransferBuffer, public AudioReadab
size_t free() const override;
void consume(size_t bytes) override { this->decrease_buffer_length(bytes); }
bool has_buffered_data() const override;
size_t fill(TickType_t ticks_to_wait) override { return this->transfer_data_from_source(ticks_to_wait); }
size_t fill(TickType_t ticks_to_wait, bool pre_shift) override {
return this->transfer_data_from_source(ticks_to_wait, pre_shift);
}
};
#pragma GCC diagnostic pop
/// @brief A lightweight read-only audio buffer for const data sources (e.g., flash memory).
/// Does not allocate memory or transfer data from external sources.
@@ -246,14 +256,21 @@ class RingBufferAudioSource : public AudioReadableBuffer {
size_t available() const override { return this->current_available_; }
void consume(size_t bytes) override;
bool has_buffered_data() const override;
/// pre_shift is ignored: there is no intermediate transfer buffer to compact, so an unconsumed
/// exposure stays in place and fill() returns 0 until it is fully consumed.
size_t fill(TickType_t ticks_to_wait, bool pre_shift) override;
/// An unconsumed exposure stays in place and fill() returns 0 until it is fully consumed.
size_t fill(TickType_t ticks_to_wait) override;
// Keeps the deprecated fill(ticks_to_wait, pre_shift) overload visible. Remove before 2027.5.0.
using AudioReadableBuffer::fill;
/// @brief Discards all buffered audio: releases any held ring buffer item, clears the source's in-flight
/// state, and resets the underlying ring buffer. Must be invoked from the ring buffer's consumer thread.
void clear_buffered_data();
/// @brief Zero-pads held whole frames short of an alignment unit and exposes them, so a stream's tail is not
/// stranded. A held partial frame is left to wait for its remaining bytes.
/// @param frame_bytes Bytes per audio frame
/// @return Real (unpadded) bytes exposed, or 0 if nothing is exposable
size_t expose_padded_partial(size_t frame_bytes);
/// @brief Returns a mutable pointer to the currently exposed audio data.
/// The pointer may reference the ring buffer's internal storage or, when exposing a stitched frame
/// across a wrap boundary, an internal splice buffer. In either case mutations are safe but data
@@ -12,14 +12,10 @@ DEPENDENCIES = ["bedjet"]
BedJetClimate = bedjet_ns.class_("BedJetClimate", climate.Climate, cg.PollingComponent)
BedjetHeatMode = bedjet_ns.enum("BedjetHeatMode")
BedjetTemperatureSource = bedjet_ns.enum("BedjetTemperatureSource")
BEDJET_HEAT_MODES = {
"heat": BedjetHeatMode.HEAT_MODE_HEAT,
"extended": BedjetHeatMode.HEAT_MODE_EXTENDED,
}
BEDJET_TEMPERATURE_SOURCES = {
"outlet": BedjetTemperatureSource.TEMPERATURE_SOURCE_OUTLET,
"ambient": BedjetTemperatureSource.TEMPERATURE_SOURCE_AMBIENT,
}
BEDJET_HEAT_MODES = BedjetHeatMode.options("heat", "extended", prefix="HEAT_MODE_")
BEDJET_TEMPERATURE_SOURCES = BedjetTemperatureSource.options(
"outlet", "ambient", prefix="TEMPERATURE_SOURCE_"
)
CONFIG_SCHEMA = (
climate.climate_schema(BedJetClimate)
+1 -5
View File
@@ -25,11 +25,7 @@ BH1745Component = bh1745_ns.class_(
)
AdcGain = bh1745_ns.enum("AdcGain", is_class=True)
ADC_GAINS = {
"1X": AdcGain.ADC_GAIN_1X,
"2X": AdcGain.ADC_GAIN_2X,
"16X": AdcGain.ADC_GAIN_16X,
}
ADC_GAINS = AdcGain.options("1X", "2X", "16X", prefix="ADC_GAIN_")
MeasurementTime = bh1745_ns.enum("MeasurementTime", is_class=True)
MEASUREMENT_TIMES = {
+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);
}
+3 -4
View File
@@ -35,10 +35,9 @@ CONF_ENERGY_TOTAL = "energy_total"
bl0939_ns = cg.esphome_ns.namespace("bl0939")
BL0939 = bl0939_ns.class_("BL0939", cg.PollingComponent, uart.UARTDevice)
BL0939Mode = bl0939_ns.enum("BL0939Mode", is_class=True)
MODE_OPTIONS = {
"direct": BL0939Mode.BL0939_MODE_DIRECT,
"current_transformer": BL0939Mode.BL0939_MODE_CURRENT_TRANSFORMER,
}
MODE_OPTIONS = BL0939Mode.options(
"direct", "current_transformer", prefix="BL0939_MODE_"
)
# Must match the mode_ member initializer in bl0939.h; set_mode() is skipped
# when the config already equals it.
DEFAULT_MODE = "direct"
@@ -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) {
+6 -15
View File
@@ -24,23 +24,14 @@ DOMAIN = "bme280_base"
bme280_ns = cg.esphome_ns.namespace("bme280_base")
BME280Oversampling = bme280_ns.enum("BME280Oversampling")
OVERSAMPLING_OPTIONS = {
"NONE": BME280Oversampling.BME280_OVERSAMPLING_NONE,
"1X": BME280Oversampling.BME280_OVERSAMPLING_1X,
"2X": BME280Oversampling.BME280_OVERSAMPLING_2X,
"4X": BME280Oversampling.BME280_OVERSAMPLING_4X,
"8X": BME280Oversampling.BME280_OVERSAMPLING_8X,
"16X": BME280Oversampling.BME280_OVERSAMPLING_16X,
}
OVERSAMPLING_OPTIONS = BME280Oversampling.options(
"NONE", "1X", "2X", "4X", "8X", "16X", prefix="BME280_OVERSAMPLING_"
)
BME280IIRFilter = bme280_ns.enum("BME280IIRFilter")
IIR_FILTER_OPTIONS = {
"OFF": BME280IIRFilter.BME280_IIR_FILTER_OFF,
"2X": BME280IIRFilter.BME280_IIR_FILTER_2X,
"4X": BME280IIRFilter.BME280_IIR_FILTER_4X,
"8X": BME280IIRFilter.BME280_IIR_FILTER_8X,
"16X": BME280IIRFilter.BME280_IIR_FILTER_16X,
}
IIR_FILTER_OPTIONS = BME280IIRFilter.options(
"OFF", "2X", "4X", "8X", "16X", prefix="BME280_IIR_FILTER_"
)
CONFIG_SCHEMA_BASE = cv.Schema(
{
+6 -21
View File
@@ -3,12 +3,11 @@
#include "bme280_base.h"
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#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 +99,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;
}
@@ -148,11 +145,10 @@ void BME280Component::setup() {
this->calibration_.h1 = read_u8_(BME280_REGISTER_DIG_H1);
this->calibration_.h2 = read_s16_le_(BME280_REGISTER_DIG_H2);
this->calibration_.h3 = read_u8_(BME280_REGISTER_DIG_H3);
// h4 and h5 are signed 12-bit values; shift left then arithmetic right shift to sign-extend
int16_t h4_raw = read_u8_(BME280_REGISTER_DIG_H4) << 4 | (read_u8_(BME280_REGISTER_DIG_H4 + 1) & 0x0F);
this->calibration_.h4 = static_cast<int16_t>(h4_raw << 4) >> 4;
int16_t h5_raw = read_u8_(BME280_REGISTER_DIG_H5 + 1) << 4 | (read_u8_(BME280_REGISTER_DIG_H5) >> 4);
this->calibration_.h5 = static_cast<int16_t>(h5_raw << 4) >> 4;
this->calibration_.h4 =
sign_extend<12>(read_u8_(BME280_REGISTER_DIG_H4) << 4 | (read_u8_(BME280_REGISTER_DIG_H4 + 1) & 0x0F));
this->calibration_.h5 =
sign_extend<12>(read_u8_(BME280_REGISTER_DIG_H5 + 1) << 4 | (read_u8_(BME280_REGISTER_DIG_H5) >> 4));
this->calibration_.h6 = read_u8_(BME280_REGISTER_DIG_H6);
uint8_t humid_control_val = 0;
@@ -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.
+6 -18
View File
@@ -28,26 +28,14 @@ DEPENDENCIES = ["i2c"]
bme680_ns = cg.esphome_ns.namespace("bme680")
BME680Oversampling = bme680_ns.enum("BME680Oversampling")
OVERSAMPLING_OPTIONS = {
"NONE": BME680Oversampling.BME680_OVERSAMPLING_NONE,
"1X": BME680Oversampling.BME680_OVERSAMPLING_1X,
"2X": BME680Oversampling.BME680_OVERSAMPLING_2X,
"4X": BME680Oversampling.BME680_OVERSAMPLING_4X,
"8X": BME680Oversampling.BME680_OVERSAMPLING_8X,
"16X": BME680Oversampling.BME680_OVERSAMPLING_16X,
}
OVERSAMPLING_OPTIONS = BME680Oversampling.options(
"NONE", "1X", "2X", "4X", "8X", "16X", prefix="BME680_OVERSAMPLING_"
)
BME680IIRFilter = bme680_ns.enum("BME680IIRFilter")
IIR_FILTER_OPTIONS = {
"OFF": BME680IIRFilter.BME680_IIR_FILTER_OFF,
"1X": BME680IIRFilter.BME680_IIR_FILTER_1X,
"3X": BME680IIRFilter.BME680_IIR_FILTER_3X,
"7X": BME680IIRFilter.BME680_IIR_FILTER_7X,
"15X": BME680IIRFilter.BME680_IIR_FILTER_15X,
"31X": BME680IIRFilter.BME680_IIR_FILTER_31X,
"63X": BME680IIRFilter.BME680_IIR_FILTER_63X,
"127X": BME680IIRFilter.BME680_IIR_FILTER_127X,
}
IIR_FILTER_OPTIONS = BME680IIRFilter.options(
"OFF", "1X", "3X", "7X", "15X", "31X", "63X", "127X", prefix="BME680_IIR_FILTER_"
)
BME680Component = bme680_ns.class_(
"BME680Component", cg.PollingComponent, i2c.I2CDevice
+2 -8
View File
@@ -19,10 +19,7 @@ CONF_SUPPLY_VOLTAGE = "supply_voltage"
bme680_bsec_ns = cg.esphome_ns.namespace("bme680_bsec")
IAQMode = bme680_bsec_ns.enum("IAQMode")
IAQ_MODE_OPTIONS = {
"STATIC": IAQMode.IAQ_MODE_STATIC,
"MOBILE": IAQMode.IAQ_MODE_MOBILE,
}
IAQ_MODE_OPTIONS = IAQMode.options("STATIC", "MOBILE", prefix="IAQ_MODE_")
SupplyVoltage = bme680_bsec_ns.enum("SupplyVoltage")
SUPPLY_VOLTAGE_OPTIONS = {
@@ -31,10 +28,7 @@ SUPPLY_VOLTAGE_OPTIONS = {
}
SampleRate = bme680_bsec_ns.enum("SampleRate")
SAMPLE_RATE_OPTIONS = {
"LP": SampleRate.SAMPLE_RATE_LP,
"ULP": SampleRate.SAMPLE_RATE_ULP,
}
SAMPLE_RATE_OPTIONS = SampleRate.options("LP", "ULP", prefix="SAMPLE_RATE_")
BME680BSECComponent = bme680_bsec_ns.class_(
"BME680BSECComponent", cg.Component, i2c.I2CDevice
+6 -16
View File
@@ -36,28 +36,18 @@ BME68xBSEC2Component = bme68x_bsec2_ns.class_("BME68xBSEC2Component", cg.Compone
MODEL_OPTIONS = ["bme680", "bme688"]
AlgorithmOutput = bme68x_bsec2_ns.enum("AlgorithmOutput")
ALGORITHM_OUTPUT_OPTIONS = {
"classification": AlgorithmOutput.ALGORITHM_OUTPUT_CLASSIFICATION,
"regression": AlgorithmOutput.ALGORITHM_OUTPUT_REGRESSION,
}
ALGORITHM_OUTPUT_OPTIONS = AlgorithmOutput.options(
"classification", "regression", prefix="ALGORITHM_OUTPUT_"
)
OperatingAge = bme68x_bsec2_ns.enum("OperatingAge")
OPERATING_AGE_OPTIONS = {
"4d": OperatingAge.OPERATING_AGE_4D,
"28d": OperatingAge.OPERATING_AGE_28D,
}
OPERATING_AGE_OPTIONS = OperatingAge.options("4d", "28d", prefix="OPERATING_AGE_")
SampleRate = bme68x_bsec2_ns.enum("SampleRate")
SAMPLE_RATE_OPTIONS = {
"LP": SampleRate.SAMPLE_RATE_LP,
"ULP": SampleRate.SAMPLE_RATE_ULP,
}
SAMPLE_RATE_OPTIONS = SampleRate.options("LP", "ULP", prefix="SAMPLE_RATE_")
Voltage = bme68x_bsec2_ns.enum("Voltage")
VOLTAGE_OPTIONS = {
"1.8V": Voltage.VOLTAGE_1_8V,
"3.3V": Voltage.VOLTAGE_3_3V,
}
VOLTAGE_OPTIONS = Voltage.options("1.8V", "3.3V", prefix="VOLTAGE_")
ALGORITHM_OUTPUT_FILE_NAME = {
"classification": "sel",
+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)));
+3 -6
View File
@@ -20,12 +20,9 @@ CONF_AUX_DEVICE = "aux_device"
# Enum proxies (must match the C++ enum values exactly)
BMI270AuxDevice = bmi270_ns.enum("BMI270AuxDevice")
BMI270AccelRange = bmi270_ns.enum("BMI270AccelRange")
ACCEL_RANGE_OPTIONS = {
"2G": BMI270AccelRange.BMI270_ACCEL_RANGE_2G,
"4G": BMI270AccelRange.BMI270_ACCEL_RANGE_4G,
"8G": BMI270AccelRange.BMI270_ACCEL_RANGE_8G,
"16G": BMI270AccelRange.BMI270_ACCEL_RANGE_16G,
}
ACCEL_RANGE_OPTIONS = BMI270AccelRange.options(
"2G", "4G", "8G", "16G", prefix="BMI270_ACCEL_RANGE_"
)
BMI270GyroRange = bmi270_ns.enum("BMI270GyroRange")
GYRO_RANGE_OPTIONS = {
+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_);
+6 -15
View File
@@ -21,23 +21,14 @@ DOMAIN = "bmp280_base"
bmp280_ns = cg.esphome_ns.namespace("bmp280_base")
BMP280Oversampling = bmp280_ns.enum("BMP280Oversampling")
OVERSAMPLING_OPTIONS = {
"NONE": BMP280Oversampling.BMP280_OVERSAMPLING_NONE,
"1X": BMP280Oversampling.BMP280_OVERSAMPLING_1X,
"2X": BMP280Oversampling.BMP280_OVERSAMPLING_2X,
"4X": BMP280Oversampling.BMP280_OVERSAMPLING_4X,
"8X": BMP280Oversampling.BMP280_OVERSAMPLING_8X,
"16X": BMP280Oversampling.BMP280_OVERSAMPLING_16X,
}
OVERSAMPLING_OPTIONS = BMP280Oversampling.options(
"NONE", "1X", "2X", "4X", "8X", "16X", prefix="BMP280_OVERSAMPLING_"
)
BMP280IIRFilter = bmp280_ns.enum("BMP280IIRFilter")
IIR_FILTER_OPTIONS = {
"OFF": BMP280IIRFilter.BMP280_IIR_FILTER_OFF,
"2X": BMP280IIRFilter.BMP280_IIR_FILTER_2X,
"4X": BMP280IIRFilter.BMP280_IIR_FILTER_4X,
"8X": BMP280IIRFilter.BMP280_IIR_FILTER_8X,
"16X": BMP280IIRFilter.BMP280_IIR_FILTER_16X,
}
IIR_FILTER_OPTIONS = BMP280IIRFilter.options(
"OFF", "2X", "4X", "8X", "16X", prefix="BMP280_IIR_FILTER_"
)
CONFIG_SCHEMA_BASE = cv.Schema(
{
+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 -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_);
+24 -23
View File
@@ -56,29 +56,30 @@ CanbusTrigger = canbus_ns.class_(
)
CanSpeed = canbus_ns.enum("CAN_SPEED")
CAN_SPEEDS = {
"1KBPS": CanSpeed.CAN_1KBPS,
"5KBPS": CanSpeed.CAN_5KBPS,
"10KBPS": CanSpeed.CAN_10KBPS,
"12K5BPS": CanSpeed.CAN_12K5BPS,
"16KBPS": CanSpeed.CAN_16KBPS,
"20KBPS": CanSpeed.CAN_20KBPS,
"25KBPS": CanSpeed.CAN_25KBPS,
"31K25BPS": CanSpeed.CAN_31K25BPS,
"33KBPS": CanSpeed.CAN_33KBPS,
"40KBPS": CanSpeed.CAN_40KBPS,
"50KBPS": CanSpeed.CAN_50KBPS,
"80KBPS": CanSpeed.CAN_80KBPS,
"83K3BPS": CanSpeed.CAN_83K3BPS,
"95KBPS": CanSpeed.CAN_95KBPS,
"100KBPS": CanSpeed.CAN_100KBPS,
"125KBPS": CanSpeed.CAN_125KBPS,
"200KBPS": CanSpeed.CAN_200KBPS,
"250KBPS": CanSpeed.CAN_250KBPS,
"500KBPS": CanSpeed.CAN_500KBPS,
"800KBPS": CanSpeed.CAN_800KBPS,
"1000KBPS": CanSpeed.CAN_1000KBPS,
}
CAN_SPEEDS = CanSpeed.options(
"1KBPS",
"5KBPS",
"10KBPS",
"12K5BPS",
"16KBPS",
"20KBPS",
"25KBPS",
"31K25BPS",
"33KBPS",
"40KBPS",
"50KBPS",
"80KBPS",
"83K3BPS",
"95KBPS",
"100KBPS",
"125KBPS",
"200KBPS",
"250KBPS",
"500KBPS",
"800KBPS",
"1000KBPS",
prefix="CAN_",
)
def get_rate(value: str) -> int:
+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
+32 -83
View File
@@ -67,41 +67,30 @@ CONF_GDO0_PIN = "gdo0_pin"
# Enums
SyncMode = ns.enum("SyncMode", True)
SYNC_MODE = {
"None": SyncMode.SYNC_MODE_NONE,
"15/16": SyncMode.SYNC_MODE_15_16,
"16/16": SyncMode.SYNC_MODE_16_16,
"30/32": SyncMode.SYNC_MODE_30_32,
}
SYNC_MODE = SyncMode.options("None", "15/16", "16/16", "30/32", prefix="SYNC_MODE_")
Modulation = ns.enum("Modulation", True)
MODULATION = {
"2-FSK": Modulation.MODULATION_2_FSK,
"GFSK": Modulation.MODULATION_GFSK,
"ASK/OOK": Modulation.MODULATION_ASK_OOK,
"4-FSK": Modulation.MODULATION_4_FSK,
"MSK": Modulation.MODULATION_MSK,
}
MODULATION = Modulation.options(
"2-FSK", "GFSK", "ASK/OOK", "4-FSK", "MSK", prefix="MODULATION_"
)
RxAttenuation = ns.enum("RxAttenuation", True)
RX_ATTENUATION = {
"0dB": RxAttenuation.RX_ATTENUATION_0DB,
"6dB": RxAttenuation.RX_ATTENUATION_6DB,
"12dB": RxAttenuation.RX_ATTENUATION_12DB,
"18dB": RxAttenuation.RX_ATTENUATION_18DB,
}
RX_ATTENUATION = RxAttenuation.options(
"0dB", "6dB", "12dB", "18dB", prefix="RX_ATTENUATION_"
)
MagnTarget = ns.enum("MagnTarget", True)
MAGN_TARGET = {
"24dB": MagnTarget.MAGN_TARGET_24DB,
"27dB": MagnTarget.MAGN_TARGET_27DB,
"30dB": MagnTarget.MAGN_TARGET_30DB,
"33dB": MagnTarget.MAGN_TARGET_33DB,
"36dB": MagnTarget.MAGN_TARGET_36DB,
"38dB": MagnTarget.MAGN_TARGET_38DB,
"40dB": MagnTarget.MAGN_TARGET_40DB,
"42dB": MagnTarget.MAGN_TARGET_42DB,
}
MAGN_TARGET = MagnTarget.options(
"24dB",
"27dB",
"30dB",
"33dB",
"36dB",
"38dB",
"40dB",
"42dB",
prefix="MAGN_TARGET_",
)
MaxLnaGain = ns.enum("MaxLnaGain", True)
MAX_LNA_GAIN = {
@@ -140,20 +129,14 @@ FILTER_LENGTH_FSK_MSK = {
}
FilterLengthAskOok = ns.enum("FilterLengthAskOok", True)
FILTER_LENGTH_ASK_OOK = {
"4dB": FilterLengthAskOok.FILTER_LENGTH_4DB,
"8dB": FilterLengthAskOok.FILTER_LENGTH_8DB,
"12dB": FilterLengthAskOok.FILTER_LENGTH_12DB,
"16dB": FilterLengthAskOok.FILTER_LENGTH_16DB,
}
FILTER_LENGTH_ASK_OOK = FilterLengthAskOok.options(
"4dB", "8dB", "12dB", "16dB", prefix="FILTER_LENGTH_"
)
Freeze = ns.enum("Freeze", True)
FREEZE = {
"Default": Freeze.FREEZE_DEFAULT,
"On Sync": Freeze.FREEZE_ON_SYNC,
"Analog Only": Freeze.FREEZE_ANALOG_ONLY,
"Analog And Digital": Freeze.FREEZE_ANALOG_AND_DIGITAL,
}
FREEZE = Freeze.options(
"Default", "On Sync", "Analog Only", "Analog And Digital", prefix="FREEZE_"
)
WaitTime = ns.enum("WaitTime", True)
WAIT_TIME = {
@@ -164,34 +147,16 @@ WAIT_TIME = {
}
HystLevel = ns.enum("HystLevel", True)
HYST_LEVEL = {
"None": HystLevel.HYST_LEVEL_NONE,
"Low": HystLevel.HYST_LEVEL_LOW,
"Medium": HystLevel.HYST_LEVEL_MEDIUM,
"High": HystLevel.HYST_LEVEL_HIGH,
}
HYST_LEVEL = HystLevel.options("None", "Low", "Medium", "High", prefix="HYST_LEVEL_")
FocLimit = ns.enum("FocLimit", True)
FOC_LIMIT = {
"Disabled": FocLimit.FOC_LIMIT_DISABLED,
"BW/8": FocLimit.FOC_LIMIT_BW_8,
"BW/4": FocLimit.FOC_LIMIT_BW_4,
"BW/2": FocLimit.FOC_LIMIT_BW_2,
}
FOC_LIMIT = FocLimit.options("Disabled", "BW/8", "BW/4", "BW/2", prefix="FOC_LIMIT_")
FocPreK = ns.enum("FocPreK", True)
FOC_PRE_K = {
"K": FocPreK.FOC_PRE_K_K,
"2K": FocPreK.FOC_PRE_K_2K,
"3K": FocPreK.FOC_PRE_K_3K,
"4K": FocPreK.FOC_PRE_K_4K,
}
FOC_PRE_K = FocPreK.options("K", "2K", "3K", "4K", prefix="FOC_PRE_K_")
FocPostK = ns.enum("FocPostK", True)
FOC_POST_K = {
"Same": FocPostK.FOC_POST_K_SAME,
"K/2": FocPostK.FOC_POST_K_K_2,
}
FOC_POST_K = FocPostK.options("Same", "K/2", prefix="FOC_POST_K_")
BsLimit = ns.enum("BsLimit", True)
BS_LIMIT = {
@@ -202,32 +167,16 @@ BS_LIMIT = {
}
BsPreKi = ns.enum("BsPreKi", True)
BS_PRE_KI = {
"KI": BsPreKi.BS_PRE_KI_KI,
"2KI": BsPreKi.BS_PRE_KI_2KI,
"3KI": BsPreKi.BS_PRE_KI_3KI,
"4KI": BsPreKi.BS_PRE_KI_4KI,
}
BS_PRE_KI = BsPreKi.options("KI", "2KI", "3KI", "4KI", prefix="BS_PRE_KI_")
BsPreKp = ns.enum("BsPreKp", True)
BS_PRE_KP = {
"KP": BsPreKp.BS_PRE_KP_KP,
"2KP": BsPreKp.BS_PRE_KP_2KP,
"3KP": BsPreKp.BS_PRE_KP_3KP,
"4KP": BsPreKp.BS_PRE_KP_4KP,
}
BS_PRE_KP = BsPreKp.options("KP", "2KP", "3KP", "4KP", prefix="BS_PRE_KP_")
BsPostKi = ns.enum("BsPostKi", True)
BS_POST_KI = {
"Same": BsPostKi.BS_POST_KI_SAME,
"KI/2": BsPostKi.BS_POST_KI_KI_2,
}
BS_POST_KI = BsPostKi.options("Same", "KI/2", prefix="BS_POST_KI_")
BsPostKp = ns.enum("BsPostKp", True)
BS_POST_KP = {
"Same": BsPostKp.BS_POST_KP_SAME,
"KP": BsPostKp.BS_POST_KP_KP,
}
BS_POST_KP = BsPostKp.options("Same", "KP", prefix="BS_POST_KP_")
# Optional settings to generate setter calls for
CONFIG_MAP = {
+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) {
+47 -46
View File
@@ -69,67 +69,68 @@ ClimateCall = climate_ns.class_("ClimateCall")
ClimateTraits = climate_ns.class_("ClimateTraits")
ClimateMode = climate_ns.enum("ClimateMode")
CLIMATE_MODES = {
"OFF": ClimateMode.CLIMATE_MODE_OFF,
"HEAT_COOL": ClimateMode.CLIMATE_MODE_HEAT_COOL,
"COOL": ClimateMode.CLIMATE_MODE_COOL,
"HEAT": ClimateMode.CLIMATE_MODE_HEAT,
"DRY": ClimateMode.CLIMATE_MODE_DRY,
"FAN_ONLY": ClimateMode.CLIMATE_MODE_FAN_ONLY,
"AUTO": ClimateMode.CLIMATE_MODE_AUTO,
}
CLIMATE_MODES = ClimateMode.options(
"OFF",
"HEAT_COOL",
"COOL",
"HEAT",
"DRY",
"FAN_ONLY",
"AUTO",
prefix="CLIMATE_MODE_",
)
validate_climate_mode = cv.enum(CLIMATE_MODES, upper=True)
ClimateFanMode = climate_ns.enum("ClimateFanMode")
CLIMATE_FAN_MODES = {
"ON": ClimateFanMode.CLIMATE_FAN_ON,
"OFF": ClimateFanMode.CLIMATE_FAN_OFF,
"AUTO": ClimateFanMode.CLIMATE_FAN_AUTO,
"LOW": ClimateFanMode.CLIMATE_FAN_LOW,
"MEDIUM": ClimateFanMode.CLIMATE_FAN_MEDIUM,
"HIGH": ClimateFanMode.CLIMATE_FAN_HIGH,
"MIDDLE": ClimateFanMode.CLIMATE_FAN_MIDDLE,
"FOCUS": ClimateFanMode.CLIMATE_FAN_FOCUS,
"DIFFUSE": ClimateFanMode.CLIMATE_FAN_DIFFUSE,
"QUIET": ClimateFanMode.CLIMATE_FAN_QUIET,
}
CLIMATE_FAN_MODES = ClimateFanMode.options(
"ON",
"OFF",
"AUTO",
"LOW",
"MEDIUM",
"HIGH",
"MIDDLE",
"FOCUS",
"DIFFUSE",
"QUIET",
prefix="CLIMATE_FAN_",
)
validate_climate_fan_mode = cv.enum(CLIMATE_FAN_MODES, upper=True)
ClimatePreset = climate_ns.enum("ClimatePreset")
CLIMATE_PRESETS = {
"NONE": ClimatePreset.CLIMATE_PRESET_NONE,
"ECO": ClimatePreset.CLIMATE_PRESET_ECO,
"AWAY": ClimatePreset.CLIMATE_PRESET_AWAY,
"BOOST": ClimatePreset.CLIMATE_PRESET_BOOST,
"COMFORT": ClimatePreset.CLIMATE_PRESET_COMFORT,
"HOME": ClimatePreset.CLIMATE_PRESET_HOME,
"SLEEP": ClimatePreset.CLIMATE_PRESET_SLEEP,
"ACTIVITY": ClimatePreset.CLIMATE_PRESET_ACTIVITY,
}
CLIMATE_PRESETS = ClimatePreset.options(
"NONE",
"ECO",
"AWAY",
"BOOST",
"COMFORT",
"HOME",
"SLEEP",
"ACTIVITY",
prefix="CLIMATE_PRESET_",
)
validate_climate_preset = cv.enum(CLIMATE_PRESETS, upper=True)
ClimateSwingMode = climate_ns.enum("ClimateSwingMode")
CLIMATE_SWING_MODES = {
"OFF": ClimateSwingMode.CLIMATE_SWING_OFF,
"BOTH": ClimateSwingMode.CLIMATE_SWING_BOTH,
"VERTICAL": ClimateSwingMode.CLIMATE_SWING_VERTICAL,
"HORIZONTAL": ClimateSwingMode.CLIMATE_SWING_HORIZONTAL,
}
CLIMATE_SWING_MODES = ClimateSwingMode.options(
"OFF", "BOTH", "VERTICAL", "HORIZONTAL", prefix="CLIMATE_SWING_"
)
validate_climate_swing_mode = cv.enum(CLIMATE_SWING_MODES, upper=True)
ClimateAction = climate_ns.enum("ClimateAction")
CLIMATE_ACTIONS = {
"OFF": ClimateAction.CLIMATE_ACTION_OFF,
"COOLING": ClimateAction.CLIMATE_ACTION_COOLING,
"HEATING": ClimateAction.CLIMATE_ACTION_HEATING,
"IDLE": ClimateAction.CLIMATE_ACTION_IDLE,
"DRYING": ClimateAction.CLIMATE_ACTION_DRYING,
"FAN": ClimateAction.CLIMATE_ACTION_FAN,
"DEFROSTING": ClimateAction.CLIMATE_ACTION_DEFROSTING,
}
CLIMATE_ACTIONS = ClimateAction.options(
"OFF",
"COOLING",
"HEATING",
"IDLE",
"DRYING",
"FAN",
"DEFROSTING",
prefix="CLIMATE_ACTION_",
)
validate_climate_action = cv.enum(CLIMATE_ACTIONS, upper=True)
+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"
+3 -5
View File
@@ -80,11 +80,9 @@ COVER_STATES = {
validate_cover_state = cv.enum(COVER_STATES, upper=True)
CoverOperation = cover_ns.enum("CoverOperation")
COVER_OPERATIONS = {
"IDLE": CoverOperation.COVER_OPERATION_IDLE,
"OPENING": CoverOperation.COVER_OPERATION_OPENING,
"CLOSING": CoverOperation.COVER_OPERATION_CLOSING,
}
COVER_OPERATIONS = CoverOperation.options(
"IDLE", "OPENING", "CLOSING", prefix="COVER_OPERATION_"
)
validate_cover_operation = cv.enum(COVER_OPERATIONS, upper=True)
# Actions
+2 -1
View File
@@ -1,4 +1,5 @@
#include "cs5460a.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
namespace esphome::cs5460a {
@@ -304,7 +305,7 @@ bool CS5460AComponent::check_status_() {
voltage_sensor_->publish_state(raw_voltage * voltage_multiplier_);
if (power_sensor_ != nullptr && raw_energy != prev_raw_energy_) {
int32_t raw = (int32_t) (raw_energy << 8) >> 8; /* Sign-extend */
int32_t raw = sign_extend<24>(raw_energy);
power_sensor_->publish_state(raw * power_multiplier_);
prev_raw_energy_ = raw_energy;
}
+1 -4
View File
@@ -24,10 +24,7 @@ DEPENDENCIES = ["spi"]
cs5460a_ns = cg.esphome_ns.namespace("cs5460a")
CS5460APGAGain = cs5460a_ns.enum("CS5460APGAGain")
PGA_GAIN_OPTIONS = {
"10X": CS5460APGAGain.CS5460A_PGA_GAIN_10X,
"50X": CS5460APGAGain.CS5460A_PGA_GAIN_50X,
}
PGA_GAIN_OPTIONS = CS5460APGAGain.options("10X", "50X", prefix="CS5460A_PGA_GAIN_")
CS5460AComponent = cs5460a_ns.class_("CS5460AComponent", spi.SPIDevice, cg.Component)
+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);
+3 -4
View File
@@ -39,10 +39,9 @@ CONF_POWER_FACTOR_1 = "power_factor_1"
CONF_CURRENT_INPUT = "current_input"
CSE7761CurrentInput = cse7761_ns.enum("CSE7761CurrentInput", is_class=True)
CURRENT_INPUTS = {
"shunt": CSE7761CurrentInput.CSE7761_CURRENT_INPUT_SHUNT,
"current_transformer": CSE7761CurrentInput.CSE7761_CURRENT_INPUT_CURRENT_TRANSFORMER,
}
CURRENT_INPUTS = CSE7761CurrentInput.options(
"shunt", "current_transformer", prefix="CSE7761_CURRENT_INPUT_"
)
CONFIG_SCHEMA = (
cv.Schema(
@@ -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");
}
}
+6 -10
View File
@@ -223,19 +223,15 @@ DeepSleepComponent = deep_sleep_ns.class_("DeepSleepComponent", cg.Component)
EnterDeepSleepAction = deep_sleep_ns.class_("EnterDeepSleepAction", automation.Action)
WakeupPinMode = deep_sleep_ns.enum("WakeupPinMode")
WAKEUP_PIN_MODES = {
"IGNORE": WakeupPinMode.WAKEUP_PIN_MODE_IGNORE,
"KEEP_AWAKE": WakeupPinMode.WAKEUP_PIN_MODE_KEEP_AWAKE,
"INVERT_WAKEUP": WakeupPinMode.WAKEUP_PIN_MODE_INVERT_WAKEUP,
}
WAKEUP_PIN_MODES = WakeupPinMode.options(
"IGNORE", "KEEP_AWAKE", "INVERT_WAKEUP", prefix="WAKEUP_PIN_MODE_"
)
esp_sleep_ext1_wakeup_mode_t = cg.global_ns.enum("esp_sleep_ext1_wakeup_mode_t")
Ext1Wakeup = deep_sleep_ns.struct("Ext1Wakeup")
EXT1_WAKEUP_MODES = {
"ANY_LOW": esp_sleep_ext1_wakeup_mode_t.ESP_EXT1_WAKEUP_ANY_LOW,
"ALL_LOW": esp_sleep_ext1_wakeup_mode_t.ESP_EXT1_WAKEUP_ALL_LOW,
"ANY_HIGH": esp_sleep_ext1_wakeup_mode_t.ESP_EXT1_WAKEUP_ANY_HIGH,
}
EXT1_WAKEUP_MODES = esp_sleep_ext1_wakeup_mode_t.options(
"ANY_LOW", "ALL_LOW", "ANY_HIGH", prefix="ESP_EXT1_WAKEUP_"
)
WakeupCauseToRunDuration = deep_sleep_ns.struct("WakeupCauseToRunDuration")
WakeupCause = deep_sleep_ns.enum("WakeupCause")
+2 -12
View File
@@ -21,19 +21,9 @@ CONF_EQ_PRESET = "eq_preset"
CONF_ON_FINISHED_PLAYBACK = "on_finished_playback"
EqPreset = dfplayer_ns.enum("EqPreset")
EQ_PRESET = {
"NORMAL": EqPreset.NORMAL,
"POP": EqPreset.POP,
"ROCK": EqPreset.ROCK,
"JAZZ": EqPreset.JAZZ,
"CLASSIC": EqPreset.CLASSIC,
"BASS": EqPreset.BASS,
}
EQ_PRESET = EqPreset.options("NORMAL", "POP", "ROCK", "JAZZ", "CLASSIC", "BASS")
Device = dfplayer_ns.enum("Device")
DEVICE = {
"USB": Device.USB,
"TF_CARD": Device.TF_CARD,
}
DEVICE = Device.options("USB", "TF_CARD")
CONFIG_SCHEMA = cv.All(
cv.Schema(
@@ -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};
};
+11 -10
View File
@@ -19,16 +19,17 @@ from esphome.types import ConfigType
dht_ns = cg.esphome_ns.namespace("dht")
DHTModel = dht_ns.enum("DHTModel")
DHT_MODELS = {
"AUTO_DETECT": DHTModel.DHT_MODEL_AUTO_DETECT,
"DHT11": DHTModel.DHT_MODEL_DHT11,
"DHT22": DHTModel.DHT_MODEL_DHT22,
"AM2120": DHTModel.DHT_MODEL_AM2120,
"AM2302": DHTModel.DHT_MODEL_AM2302,
"RHT03": DHTModel.DHT_MODEL_RHT03,
"SI7021": DHTModel.DHT_MODEL_SI7021,
"DHT22_TYPE2": DHTModel.DHT_MODEL_DHT22_TYPE2,
}
DHT_MODELS = DHTModel.options(
"AUTO_DETECT",
"DHT11",
"DHT22",
"AM2120",
"AM2302",
"RHT03",
"SI7021",
"DHT22_TYPE2",
prefix="DHT_MODEL_",
)
DHT = dht_ns.class_("DHT", cg.PollingComponent)
CONFIG_SCHEMA = cv.Schema(
+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_);

Some files were not shown because too many files have changed in this diff Show More