mirror of
https://github.com/esphome/esphome.git
synced 2024-11-26 12:27:13 +01:00
commit
6ced54ea8e
@ -160,7 +160,7 @@ light::ESPColorView ESP32RMTLEDStripLightOutput::get_view_internal(int32_t index
|
||||
b = 0;
|
||||
break;
|
||||
}
|
||||
uint8_t multiplier = this->is_rgbw_ ? 4 : 3;
|
||||
uint8_t multiplier = this->is_rgbw_ || this->is_wrgb_ ? 4 : 3;
|
||||
uint8_t white = this->is_wrgb_ ? 0 : 3;
|
||||
|
||||
return {this->buf_ + (index * multiplier) + r + this->is_wrgb_,
|
||||
|
@ -103,6 +103,7 @@ KEY_AUTHOR = "author"
|
||||
KEY_WEBSITE = "website"
|
||||
KEY_VERSION = "version"
|
||||
KEY_MICRO = "micro"
|
||||
KEY_MINIMUM_ESPHOME_VERSION = "minimum_esphome_version"
|
||||
|
||||
MANIFEST_SCHEMA_V1 = cv.Schema(
|
||||
{
|
||||
@ -116,6 +117,9 @@ MANIFEST_SCHEMA_V1 = cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_PROBABILITY_CUTOFF): cv.float_,
|
||||
cv.Required(CONF_SLIDING_WINDOW_AVERAGE_SIZE): cv.positive_int,
|
||||
cv.Optional(KEY_MINIMUM_ESPHOME_VERSION): cv.All(
|
||||
cv.version_number, cv.validate_esphome_version
|
||||
),
|
||||
}
|
||||
),
|
||||
}
|
||||
@ -261,7 +265,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(MicroWakeWord),
|
||||
cv.GenerateID(CONF_MICROPHONE): cv.use_id(microphone.Microphone),
|
||||
cv.Optional(CONF_PROBABILITY_CUTOFF): cv.float_,
|
||||
cv.Optional(CONF_PROBABILITY_CUTOFF): cv.percentage,
|
||||
cv.Optional(CONF_SLIDING_WINDOW_AVERAGE_SIZE): cv.positive_int,
|
||||
cv.Optional(CONF_ON_WAKE_WORD_DETECTED): automation.validate_automation(
|
||||
single=True
|
||||
|
@ -53,8 +53,15 @@ static const LogString *micro_wake_word_state_to_string(State state) {
|
||||
}
|
||||
}
|
||||
|
||||
void MicroWakeWord::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "microWakeWord:");
|
||||
ESP_LOGCONFIG(TAG, " Wake Word: %s", this->get_wake_word().c_str());
|
||||
ESP_LOGCONFIG(TAG, " Probability cutoff: %.3f", this->probability_cutoff_);
|
||||
ESP_LOGCONFIG(TAG, " Sliding window size: %d", this->sliding_window_average_size_);
|
||||
}
|
||||
|
||||
void MicroWakeWord::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up Micro Wake Word...");
|
||||
ESP_LOGCONFIG(TAG, "Setting up microWakeWord...");
|
||||
|
||||
if (!this->initialize_models()) {
|
||||
ESP_LOGE(TAG, "Failed to initialize models");
|
||||
@ -63,7 +70,7 @@ void MicroWakeWord::setup() {
|
||||
}
|
||||
|
||||
ExternalRAMAllocator<int16_t> allocator(ExternalRAMAllocator<int16_t>::ALLOW_FAILURE);
|
||||
this->input_buffer_ = allocator.allocate(NEW_SAMPLES_TO_GET);
|
||||
this->input_buffer_ = allocator.allocate(INPUT_BUFFER_SIZE * sizeof(int16_t));
|
||||
if (this->input_buffer_ == nullptr) {
|
||||
ESP_LOGW(TAG, "Could not allocate input buffer");
|
||||
this->mark_failed();
|
||||
@ -81,7 +88,7 @@ void MicroWakeWord::setup() {
|
||||
}
|
||||
|
||||
int MicroWakeWord::read_microphone_() {
|
||||
size_t bytes_read = this->microphone_->read(this->input_buffer_, NEW_SAMPLES_TO_GET * sizeof(int16_t));
|
||||
size_t bytes_read = this->microphone_->read(this->input_buffer_, INPUT_BUFFER_SIZE * sizeof(int16_t));
|
||||
if (bytes_read == 0) {
|
||||
return 0;
|
||||
}
|
||||
@ -279,11 +286,6 @@ bool MicroWakeWord::initialize_models() {
|
||||
}
|
||||
|
||||
bool MicroWakeWord::update_features_() {
|
||||
// Verify we have enough samples for a feature slice
|
||||
if (!this->slice_available_()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve strided audio samples
|
||||
int16_t *audio_samples = nullptr;
|
||||
if (!this->stride_audio_samples_(&audio_samples)) {
|
||||
@ -369,20 +371,36 @@ void MicroWakeWord::set_sliding_window_average_size(size_t size) {
|
||||
bool MicroWakeWord::slice_available_() {
|
||||
size_t available = this->ring_buffer_->available();
|
||||
|
||||
size_t free = this->ring_buffer_->free();
|
||||
|
||||
if (free < NEW_SAMPLES_TO_GET * sizeof(int16_t)) {
|
||||
// If the ring buffer is within one audio slice of being full, then wake word detection will have issues.
|
||||
// If this is constantly occuring, then some possibilities why are
|
||||
// 1) there are too many other slow components configured
|
||||
// 2) the ESP32 isn't fast enough; e.g., an ESP32 is much slower than an ESP32-S3 at inferences.
|
||||
// 3) the model is too large
|
||||
// 4) the model uses operations that are not optimized
|
||||
ESP_LOGW(TAG,
|
||||
"Audio buffer is nearly full. Wake word detection may be less accurate and have slower reponse times. "
|
||||
#if !defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
"microWakeWord is designed for the ESP32-S3. The current platform is too slow for this model."
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
return available > (NEW_SAMPLES_TO_GET * sizeof(int16_t));
|
||||
}
|
||||
|
||||
bool MicroWakeWord::stride_audio_samples_(int16_t **audio_samples) {
|
||||
if (!this->slice_available_()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy 320 bytes (160 samples over 10 ms) into preprocessor_audio_buffer_ from history in
|
||||
// preprocessor_stride_buffer_
|
||||
memcpy((void *) (this->preprocessor_audio_buffer_), (void *) (this->preprocessor_stride_buffer_),
|
||||
HISTORY_SAMPLES_TO_KEEP * sizeof(int16_t));
|
||||
|
||||
if (this->ring_buffer_->available() < NEW_SAMPLES_TO_GET * sizeof(int16_t)) {
|
||||
ESP_LOGD(TAG, "Audio Buffer not full enough");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy 640 bytes (320 samples over 20 ms) from the ring buffer
|
||||
// The first 320 bytes (160 samples over 10 ms) will be from history
|
||||
size_t bytes_read = this->ring_buffer_->read((void *) (this->preprocessor_audio_buffer_ + HISTORY_SAMPLES_TO_KEEP),
|
||||
|
@ -66,6 +66,7 @@ class MicroWakeWord : public Component {
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
float get_setup_priority() const override;
|
||||
void dump_config() override;
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
@ -74,6 +75,8 @@ class MicroWakeWord : public Component {
|
||||
|
||||
bool initialize_models();
|
||||
|
||||
std::string get_wake_word() { return this->wake_word_; }
|
||||
|
||||
// Increasing either of these will reduce the rate of false acceptances while increasing the false rejection rate
|
||||
void set_probability_cutoff(float probability_cutoff) { this->probability_cutoff_ = probability_cutoff; }
|
||||
void set_sliding_window_average_size(size_t size);
|
||||
|
@ -14,7 +14,7 @@ static const uint8_t NBITS_ADDRESS = 16;
|
||||
static const uint8_t NBITS_CHANNEL = 5;
|
||||
static const uint8_t NBITS_COMMAND = 7;
|
||||
static const uint8_t NDATABITS = NBITS_ADDRESS + NBITS_CHANNEL + NBITS_COMMAND;
|
||||
static const uint8_t MIN_RX_SRC = (NDATABITS * 2 + NBITS_SYNC / 2);
|
||||
static const uint8_t MIN_RX_SRC = (NDATABITS + NBITS_SYNC / 2);
|
||||
|
||||
static const uint8_t CMD_ON = 0x41;
|
||||
static const uint8_t CMD_OFF = 0x02;
|
||||
@ -135,7 +135,7 @@ optional<DraytonData> DraytonProtocol::decode(RemoteReceiveData src) {
|
||||
.command = 0,
|
||||
};
|
||||
|
||||
while (src.size() - src.get_index() > MIN_RX_SRC) {
|
||||
while (src.size() - src.get_index() >= MIN_RX_SRC) {
|
||||
ESP_LOGVV(TAG,
|
||||
"Decode Drayton: %" PRId32 ", %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32
|
||||
" %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32
|
||||
@ -150,7 +150,7 @@ optional<DraytonData> DraytonProtocol::decode(RemoteReceiveData src) {
|
||||
}
|
||||
|
||||
// Look for sync pulse, after. If sucessful index points to space of sync symbol
|
||||
while (src.size() - src.get_index() >= NDATABITS) {
|
||||
while (src.size() - src.get_index() >= MIN_RX_SRC) {
|
||||
ESP_LOGVV(TAG, "Decode Drayton: sync search %d, %" PRId32 " %" PRId32, src.size() - src.get_index(), src.peek(),
|
||||
src.peek(1));
|
||||
if (src.peek_mark(2 * BIT_TIME_US) &&
|
||||
|
@ -29,7 +29,8 @@ from esphome.const import (
|
||||
from esphome.core import HexInt, CORE
|
||||
|
||||
DOMAIN = "shelly_dimmer"
|
||||
DEPENDENCIES = ["sensor", "uart", "esp8266"]
|
||||
AUTO_LOAD = ["sensor"]
|
||||
DEPENDENCIES = ["uart", "esp8266"]
|
||||
|
||||
shelly_dimmer_ns = cg.esphome_ns.namespace("shelly_dimmer")
|
||||
ShellyDimmer = shelly_dimmer_ns.class_(
|
||||
|
@ -36,14 +36,14 @@ bool XL9535Component::digital_read(uint8_t pin) {
|
||||
return state;
|
||||
}
|
||||
|
||||
state = (port & (pin - 10)) != 0;
|
||||
state = (port & (1 << (pin - 10))) != 0;
|
||||
} else {
|
||||
if (this->read_register(XL9535_INPUT_PORT_0_REGISTER, &port, 1) != i2c::ERROR_OK) {
|
||||
this->status_set_warning();
|
||||
return state;
|
||||
}
|
||||
|
||||
state = (port & pin) != 0;
|
||||
state = (port & (1 << pin)) != 0;
|
||||
}
|
||||
|
||||
this->status_clear_warning();
|
||||
|
@ -57,6 +57,7 @@ from esphome.const import (
|
||||
TYPE_GIT,
|
||||
TYPE_LOCAL,
|
||||
VALID_SUBSTITUTIONS_CHARACTERS,
|
||||
__version__ as ESPHOME_VERSION,
|
||||
)
|
||||
from esphome.core import (
|
||||
CORE,
|
||||
@ -1895,6 +1896,16 @@ def version_number(value):
|
||||
raise Invalid("Not a valid version number") from e
|
||||
|
||||
|
||||
def validate_esphome_version(value: str):
|
||||
min_version = Version.parse(value)
|
||||
current_version = Version.parse(ESPHOME_VERSION)
|
||||
if current_version < min_version:
|
||||
raise Invalid(
|
||||
f"Your ESPHome version is too old. Please update to at least {min_version}"
|
||||
)
|
||||
return value
|
||||
|
||||
|
||||
def platformio_version_constraint(value):
|
||||
# for documentation on valid version constraints:
|
||||
# https://docs.platformio.org/en/latest/core/userguide/platforms/cmd_install.html#cmd-platform-install
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""Constants used by esphome."""
|
||||
|
||||
__version__ = "2024.2.0b1"
|
||||
__version__ = "2024.2.0b2"
|
||||
|
||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||
VALID_SUBSTITUTIONS_CHARACTERS = (
|
||||
|
@ -102,16 +102,6 @@ def valid_project_name(value: str):
|
||||
return value
|
||||
|
||||
|
||||
def validate_version(value: str):
|
||||
min_version = cv.Version.parse(value)
|
||||
current_version = cv.Version.parse(ESPHOME_VERSION)
|
||||
if current_version < min_version:
|
||||
raise cv.Invalid(
|
||||
f"Your ESPHome version is too old. Please update to at least {min_version}"
|
||||
)
|
||||
return value
|
||||
|
||||
|
||||
if "ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT" in os.environ:
|
||||
_compile_process_limit_default = min(
|
||||
int(os.environ["ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT"]),
|
||||
@ -164,7 +154,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_MIN_VERSION, default=ESPHOME_VERSION): cv.All(
|
||||
cv.version_number, validate_version
|
||||
cv.version_number, cv.validate_esphome_version
|
||||
),
|
||||
cv.Optional(
|
||||
CONF_COMPILE_PROCESS_LIMIT, default=_compile_process_limit_default
|
||||
|
Loading…
Reference in New Issue
Block a user