mirror of
https://github.com/esphome/esphome.git
synced 2024-11-24 07:58:09 +01:00
Merge remote-tracking branch 'origin/dev' into nrf52_core
This commit is contained in:
commit
07ec0a7f49
63 changed files with 611 additions and 314 deletions
4
.github/actions/build-image/action.yaml
vendored
4
.github/actions/build-image/action.yaml
vendored
|
@ -46,7 +46,7 @@ runs:
|
||||||
|
|
||||||
- name: Build and push to ghcr by digest
|
- name: Build and push to ghcr by digest
|
||||||
id: build-ghcr
|
id: build-ghcr
|
||||||
uses: docker/build-push-action@v6.3.0
|
uses: docker/build-push-action@v6.4.1
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./docker/Dockerfile
|
file: ./docker/Dockerfile
|
||||||
|
@ -69,7 +69,7 @@ runs:
|
||||||
|
|
||||||
- name: Build and push to dockerhub by digest
|
- name: Build and push to dockerhub by digest
|
||||||
id: build-dockerhub
|
id: build-dockerhub
|
||||||
uses: docker/build-push-action@v6.3.0
|
uses: docker/build-push-action@v6.4.1
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ./docker/Dockerfile
|
file: ./docker/Dockerfile
|
||||||
|
|
|
@ -214,7 +214,7 @@ esphome/components/lightwaverf/* @max246
|
||||||
esphome/components/lilygo_t5_47/touchscreen/* @jesserockz
|
esphome/components/lilygo_t5_47/touchscreen/* @jesserockz
|
||||||
esphome/components/lock/* @esphome/core
|
esphome/components/lock/* @esphome/core
|
||||||
esphome/components/logger/* @esphome/core
|
esphome/components/logger/* @esphome/core
|
||||||
esphome/components/ltr390/* @sjtrny
|
esphome/components/ltr390/* @latonita @sjtrny
|
||||||
esphome/components/ltr_als_ps/* @latonita
|
esphome/components/ltr_als_ps/* @latonita
|
||||||
esphome/components/matrix_keypad/* @ssieb
|
esphome/components/matrix_keypad/* @ssieb
|
||||||
esphome/components/max31865/* @DAVe3283
|
esphome/components/max31865/* @DAVe3283
|
||||||
|
|
|
@ -703,7 +703,8 @@ def command_rename(args, config):
|
||||||
os.remove(new_path)
|
os.remove(new_path)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
os.remove(CORE.config_path)
|
if CORE.config_path != new_path:
|
||||||
|
os.remove(CORE.config_path)
|
||||||
|
|
||||||
print(color(Fore.BOLD_GREEN, "SUCCESS"))
|
print(color(Fore.BOLD_GREEN, "SUCCESS"))
|
||||||
print()
|
print()
|
||||||
|
|
|
@ -8,7 +8,6 @@ from esphome.const import (
|
||||||
CONF_PROTOCOL,
|
CONF_PROTOCOL,
|
||||||
CONF_VISUAL,
|
CONF_VISUAL,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE
|
|
||||||
|
|
||||||
CODEOWNERS = ["@rob-deutsch"]
|
CODEOWNERS = ["@rob-deutsch"]
|
||||||
|
|
||||||
|
@ -67,6 +66,11 @@ PROTOCOLS = {
|
||||||
"carrier_qlima_2": Protocol.PROTOCOL_QLIMA_2,
|
"carrier_qlima_2": Protocol.PROTOCOL_QLIMA_2,
|
||||||
"samsung_aqv12msan": Protocol.PROTOCOL_SAMSUNG_AQV12MSAN,
|
"samsung_aqv12msan": Protocol.PROTOCOL_SAMSUNG_AQV12MSAN,
|
||||||
"zhjg01": Protocol.PROTOCOL_ZHJG01,
|
"zhjg01": Protocol.PROTOCOL_ZHJG01,
|
||||||
|
"airway": Protocol.PROTOCOL_AIRWAY,
|
||||||
|
"bgh_aud": Protocol.PROTOCOL_BGH_AUD,
|
||||||
|
"panasonic_altdke": Protocol.PROTOCOL_PANASONIC_ALTDKE,
|
||||||
|
"vaillantvai8": Protocol.PROTOCOL_VAILLANTVAI8,
|
||||||
|
"r51m": Protocol.PROTOCOL_R51M,
|
||||||
}
|
}
|
||||||
|
|
||||||
CONF_HORIZONTAL_DEFAULT = "horizontal_default"
|
CONF_HORIZONTAL_DEFAULT = "horizontal_default"
|
||||||
|
@ -122,7 +126,4 @@ def to_code(config):
|
||||||
cg.add(var.set_max_temperature(config[CONF_MAX_TEMPERATURE]))
|
cg.add(var.set_max_temperature(config[CONF_MAX_TEMPERATURE]))
|
||||||
cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE]))
|
cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE]))
|
||||||
|
|
||||||
cg.add_library("tonia/HeatpumpIR", "1.0.26")
|
cg.add_library("tonia/HeatpumpIR", "1.0.27")
|
||||||
|
|
||||||
if CORE.is_esp8266 or CORE.is_esp32:
|
|
||||||
cg.add_library("crankyoldgit/IRremoteESP8266", "2.8.6")
|
|
||||||
|
|
|
@ -61,6 +61,11 @@ const std::map<Protocol, std::function<HeatpumpIR *()>> PROTOCOL_CONSTRUCTOR_MAP
|
||||||
{PROTOCOL_QLIMA_2, []() { return new Qlima2HeatpumpIR(); }}, // NOLINT
|
{PROTOCOL_QLIMA_2, []() { return new Qlima2HeatpumpIR(); }}, // NOLINT
|
||||||
{PROTOCOL_SAMSUNG_AQV12MSAN, []() { return new SamsungAQV12MSANHeatpumpIR(); }}, // NOLINT
|
{PROTOCOL_SAMSUNG_AQV12MSAN, []() { return new SamsungAQV12MSANHeatpumpIR(); }}, // NOLINT
|
||||||
{PROTOCOL_ZHJG01, []() { return new ZHJG01HeatpumpIR(); }}, // NOLINT
|
{PROTOCOL_ZHJG01, []() { return new ZHJG01HeatpumpIR(); }}, // NOLINT
|
||||||
|
{PROTOCOL_AIRWAY, []() { return new AIRWAYHeatpumpIR(); }}, // NOLINT
|
||||||
|
{PROTOCOL_BGH_AUD, []() { return new BGHHeatpumpIR(); }}, // NOLINT
|
||||||
|
{PROTOCOL_PANASONIC_ALTDKE, []() { return new PanasonicAltDKEHeatpumpIR(); }}, // NOLINT
|
||||||
|
{PROTOCOL_VAILLANTVAI8, []() { return new VaillantHeatpumpIR(); }}, // NOLINT
|
||||||
|
{PROTOCOL_R51M, []() { return new R51MHeatpumpIR(); }}, // NOLINT
|
||||||
};
|
};
|
||||||
|
|
||||||
void HeatpumpIRClimate::setup() {
|
void HeatpumpIRClimate::setup() {
|
||||||
|
|
|
@ -61,6 +61,11 @@ enum Protocol {
|
||||||
PROTOCOL_QLIMA_2,
|
PROTOCOL_QLIMA_2,
|
||||||
PROTOCOL_SAMSUNG_AQV12MSAN,
|
PROTOCOL_SAMSUNG_AQV12MSAN,
|
||||||
PROTOCOL_ZHJG01,
|
PROTOCOL_ZHJG01,
|
||||||
|
PROTOCOL_AIRWAY,
|
||||||
|
PROTOCOL_BGH_AUD,
|
||||||
|
PROTOCOL_PANASONIC_ALTDKE,
|
||||||
|
PROTOCOL_VAILLANTVAI8,
|
||||||
|
PROTOCOL_R51M,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Simple enum to represent horizontal directios
|
// Simple enum to represent horizontal directios
|
||||||
|
|
|
@ -25,6 +25,10 @@ CONF_I2S_LRCLK_PIN = "i2s_lrclk_pin"
|
||||||
CONF_I2S_AUDIO = "i2s_audio"
|
CONF_I2S_AUDIO = "i2s_audio"
|
||||||
CONF_I2S_AUDIO_ID = "i2s_audio_id"
|
CONF_I2S_AUDIO_ID = "i2s_audio_id"
|
||||||
|
|
||||||
|
CONF_I2S_MODE = "i2s_mode"
|
||||||
|
CONF_PRIMARY = "primary"
|
||||||
|
CONF_SECONDARY = "secondary"
|
||||||
|
|
||||||
i2s_audio_ns = cg.esphome_ns.namespace("i2s_audio")
|
i2s_audio_ns = cg.esphome_ns.namespace("i2s_audio")
|
||||||
I2SAudioComponent = i2s_audio_ns.class_("I2SAudioComponent", cg.Component)
|
I2SAudioComponent = i2s_audio_ns.class_("I2SAudioComponent", cg.Component)
|
||||||
I2SAudioIn = i2s_audio_ns.class_("I2SAudioIn", cg.Parented.template(I2SAudioComponent))
|
I2SAudioIn = i2s_audio_ns.class_("I2SAudioIn", cg.Parented.template(I2SAudioComponent))
|
||||||
|
@ -32,6 +36,12 @@ I2SAudioOut = i2s_audio_ns.class_(
|
||||||
"I2SAudioOut", cg.Parented.template(I2SAudioComponent)
|
"I2SAudioOut", cg.Parented.template(I2SAudioComponent)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
i2s_mode_t = cg.global_ns.enum("i2s_mode_t")
|
||||||
|
I2S_MODE_OPTIONS = {
|
||||||
|
CONF_PRIMARY: i2s_mode_t.I2S_MODE_MASTER, # NOLINT
|
||||||
|
CONF_SECONDARY: i2s_mode_t.I2S_MODE_SLAVE, # NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
# https://github.com/espressif/esp-idf/blob/master/components/soc/{variant}/include/soc/soc_caps.h
|
# https://github.com/espressif/esp-idf/blob/master/components/soc/{variant}/include/soc/soc_caps.h
|
||||||
I2S_PORTS = {
|
I2S_PORTS = {
|
||||||
VARIANT_ESP32: 2,
|
VARIANT_ESP32: 2,
|
||||||
|
|
|
@ -7,6 +7,9 @@ from esphome.components import microphone, esp32
|
||||||
from esphome.components.adc import ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, validate_adc_pin
|
from esphome.components.adc import ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, validate_adc_pin
|
||||||
|
|
||||||
from .. import (
|
from .. import (
|
||||||
|
CONF_I2S_MODE,
|
||||||
|
CONF_PRIMARY,
|
||||||
|
I2S_MODE_OPTIONS,
|
||||||
i2s_audio_ns,
|
i2s_audio_ns,
|
||||||
I2SAudioComponent,
|
I2SAudioComponent,
|
||||||
I2SAudioIn,
|
I2SAudioIn,
|
||||||
|
@ -68,6 +71,9 @@ BASE_SCHEMA = microphone.MICROPHONE_SCHEMA.extend(
|
||||||
_validate_bits, cv.enum(BITS_PER_SAMPLE)
|
_validate_bits, cv.enum(BITS_PER_SAMPLE)
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_USE_APLL, default=False): cv.boolean,
|
cv.Optional(CONF_USE_APLL, default=False): cv.boolean,
|
||||||
|
cv.Optional(CONF_I2S_MODE, default=CONF_PRIMARY): cv.enum(
|
||||||
|
I2S_MODE_OPTIONS, lower=True
|
||||||
|
),
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
|
@ -107,6 +113,7 @@ async def to_code(config):
|
||||||
cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN]))
|
cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN]))
|
||||||
cg.add(var.set_pdm(config[CONF_PDM]))
|
cg.add(var.set_pdm(config[CONF_PDM]))
|
||||||
|
|
||||||
|
cg.add(var.set_i2s_mode(config[CONF_I2S_MODE]))
|
||||||
cg.add(var.set_channel(config[CONF_CHANNEL]))
|
cg.add(var.set_channel(config[CONF_CHANNEL]))
|
||||||
cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE]))
|
cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE]))
|
||||||
cg.add(var.set_bits_per_sample(config[CONF_BITS_PER_SAMPLE]))
|
cg.add(var.set_bits_per_sample(config[CONF_BITS_PER_SAMPLE]))
|
||||||
|
|
|
@ -46,7 +46,7 @@ void I2SAudioMicrophone::start_() {
|
||||||
return; // Waiting for another i2s to return lock
|
return; // Waiting for another i2s to return lock
|
||||||
}
|
}
|
||||||
i2s_driver_config_t config = {
|
i2s_driver_config_t config = {
|
||||||
.mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_RX),
|
.mode = (i2s_mode_t) (this->i2s_mode_ | I2S_MODE_RX),
|
||||||
.sample_rate = this->sample_rate_,
|
.sample_rate = this->sample_rate_,
|
||||||
.bits_per_sample = this->bits_per_sample_,
|
.bits_per_sample = this->bits_per_sample_,
|
||||||
.channel_format = this->channel_,
|
.channel_format = this->channel_,
|
||||||
|
@ -174,8 +174,7 @@ size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) {
|
||||||
size_t samples_read = bytes_read / sizeof(int32_t);
|
size_t samples_read = bytes_read / sizeof(int32_t);
|
||||||
samples.resize(samples_read);
|
samples.resize(samples_read);
|
||||||
for (size_t i = 0; i < samples_read; i++) {
|
for (size_t i = 0; i < samples_read; i++) {
|
||||||
int32_t temp = reinterpret_cast<int32_t *>(buf)[i] >> 14;
|
samples[i] = reinterpret_cast<int32_t *>(buf)[i] >> 16;
|
||||||
samples[i] = clamp<int16_t>(temp, INT16_MIN, INT16_MAX);
|
|
||||||
}
|
}
|
||||||
memcpy(buf, samples.data(), samples_read * sizeof(int16_t));
|
memcpy(buf, samples.data(), samples_read * sizeof(int16_t));
|
||||||
return samples_read * sizeof(int16_t);
|
return samples_read * sizeof(int16_t);
|
||||||
|
|
|
@ -30,6 +30,8 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void set_i2s_mode(i2s_mode_t mode) { this->i2s_mode_ = mode; }
|
||||||
|
|
||||||
void set_channel(i2s_channel_fmt_t channel) { this->channel_ = channel; }
|
void set_channel(i2s_channel_fmt_t channel) { this->channel_ = channel; }
|
||||||
void set_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; }
|
void set_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; }
|
||||||
void set_bits_per_sample(i2s_bits_per_sample_t bits_per_sample) { this->bits_per_sample_ = bits_per_sample; }
|
void set_bits_per_sample(i2s_bits_per_sample_t bits_per_sample) { this->bits_per_sample_ = bits_per_sample; }
|
||||||
|
@ -46,6 +48,7 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub
|
||||||
bool adc_{false};
|
bool adc_{false};
|
||||||
#endif
|
#endif
|
||||||
bool pdm_{false};
|
bool pdm_{false};
|
||||||
|
i2s_mode_t i2s_mode_{};
|
||||||
i2s_channel_fmt_t channel_;
|
i2s_channel_fmt_t channel_;
|
||||||
uint32_t sample_rate_;
|
uint32_t sample_rate_;
|
||||||
i2s_bits_per_sample_t bits_per_sample_;
|
i2s_bits_per_sample_t bits_per_sample_;
|
||||||
|
|
|
@ -57,7 +57,7 @@ optional<uint8_t> ImprovSerialComponent::read_byte_() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef USE_LOGGER_USB_CDC
|
#if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC)
|
||||||
case logger::UART_SELECTION_USB_CDC:
|
case logger::UART_SELECTION_USB_CDC:
|
||||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
if (esp_usb_console_available_for_read()) {
|
if (esp_usb_console_available_for_read()) {
|
||||||
|
@ -99,7 +99,7 @@ void ImprovSerialComponent::write_data_(std::vector<uint8_t> &data) {
|
||||||
#endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3
|
#endif // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3
|
||||||
uart_write_bytes(this->uart_num_, data.data(), data.size());
|
uart_write_bytes(this->uart_num_, data.data(), data.size());
|
||||||
break;
|
break;
|
||||||
#ifdef USE_LOGGER_USB_CDC
|
#if defined(USE_LOGGER_USB_CDC) && defined(CONFIG_ESP_CONSOLE_USB_CDC)
|
||||||
case logger::UART_SELECTION_USB_CDC: {
|
case logger::UART_SELECTION_USB_CDC: {
|
||||||
const char *msg = (char *) data.data();
|
const char *msg = (char *) data.data();
|
||||||
esp_usb_console_write_buf(msg, data.size());
|
esp_usb_console_write_buf(msg, data.size());
|
||||||
|
@ -109,6 +109,7 @@ void ImprovSerialComponent::write_data_(std::vector<uint8_t> &data) {
|
||||||
#ifdef USE_LOGGER_USB_SERIAL_JTAG
|
#ifdef USE_LOGGER_USB_SERIAL_JTAG
|
||||||
case logger::UART_SELECTION_USB_SERIAL_JTAG:
|
case logger::UART_SELECTION_USB_SERIAL_JTAG:
|
||||||
usb_serial_jtag_write_bytes((char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS);
|
usb_serial_jtag_write_bytes((char *) data.data(), data.size(), 20 / portTICK_PERIOD_MS);
|
||||||
|
delay(10);
|
||||||
usb_serial_jtag_ll_txfifo_flush(); // fixes for issue in IDF 4.4.7
|
usb_serial_jtag_ll_txfifo_flush(); // fixes for issue in IDF 4.4.7
|
||||||
break;
|
break;
|
||||||
#endif // USE_LOGGER_USB_SERIAL_JTAG
|
#endif // USE_LOGGER_USB_SERIAL_JTAG
|
||||||
|
|
|
@ -19,6 +19,7 @@ static const uint8_t LTR390_MAIN_STATUS = 0x07;
|
||||||
|
|
||||||
static const float GAINVALUES[5] = {1.0, 3.0, 6.0, 9.0, 18.0};
|
static const float GAINVALUES[5] = {1.0, 3.0, 6.0, 9.0, 18.0};
|
||||||
static const float RESOLUTIONVALUE[6] = {4.0, 2.0, 1.0, 0.5, 0.25, 0.125};
|
static const float RESOLUTIONVALUE[6] = {4.0, 2.0, 1.0, 0.5, 0.25, 0.125};
|
||||||
|
static const uint8_t RESOLUTION_BITS[6] = {20, 19, 18, 17, 16, 13};
|
||||||
|
|
||||||
// Request fastest measurement rate - will be slowed by device if conversion rate is slower.
|
// Request fastest measurement rate - will be slowed by device if conversion rate is slower.
|
||||||
static const float RESOLUTION_SETTING[6] = {0x00, 0x10, 0x20, 0x30, 0x40, 0x50};
|
static const float RESOLUTION_SETTING[6] = {0x00, 0x10, 0x20, 0x30, 0x40, 0x50};
|
||||||
|
@ -74,7 +75,7 @@ void LTR390Component::read_als_() {
|
||||||
uint32_t als = *val;
|
uint32_t als = *val;
|
||||||
|
|
||||||
if (this->light_sensor_ != nullptr) {
|
if (this->light_sensor_ != nullptr) {
|
||||||
float lux = ((0.6 * als) / (GAINVALUES[this->gain_] * RESOLUTIONVALUE[this->res_])) * this->wfac_;
|
float lux = ((0.6 * als) / (GAINVALUES[this->gain_als_] * RESOLUTIONVALUE[this->res_als_])) * this->wfac_;
|
||||||
this->light_sensor_->publish_state(lux);
|
this->light_sensor_->publish_state(lux);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +91,7 @@ void LTR390Component::read_uvs_() {
|
||||||
uint32_t uv = *val;
|
uint32_t uv = *val;
|
||||||
|
|
||||||
if (this->uvi_sensor_ != nullptr) {
|
if (this->uvi_sensor_ != nullptr) {
|
||||||
this->uvi_sensor_->publish_state((uv / this->sensitivity_) * this->wfac_);
|
this->uvi_sensor_->publish_state((uv / this->sensitivity_uv_) * this->wfac_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->uv_sensor_ != nullptr) {
|
if (this->uv_sensor_ != nullptr) {
|
||||||
|
@ -107,24 +108,38 @@ void LTR390Component::read_mode_(int mode_index) {
|
||||||
ctrl[LTR390_CTRL_EN] = true;
|
ctrl[LTR390_CTRL_EN] = true;
|
||||||
this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong();
|
this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong();
|
||||||
|
|
||||||
// After the sensor integration time do the following
|
uint32_t int_time{0};
|
||||||
this->set_timeout(((uint32_t) RESOLUTIONVALUE[this->res_]) * 100 + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME,
|
// Set gain, resolution and measurement rate
|
||||||
[this, mode_index]() {
|
switch (mode) {
|
||||||
// Read from the sensor
|
case LTR390_MODE_ALS:
|
||||||
std::get<1>(this->mode_funcs_[mode_index])();
|
this->reg(LTR390_GAIN) = this->gain_als_;
|
||||||
|
this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_als_];
|
||||||
|
int_time = ((uint32_t) RESOLUTIONVALUE[this->res_als_]) * 100;
|
||||||
|
break;
|
||||||
|
case LTR390_MODE_UVS:
|
||||||
|
this->reg(LTR390_GAIN) = this->gain_uv_;
|
||||||
|
this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_uv_];
|
||||||
|
int_time = ((uint32_t) RESOLUTIONVALUE[this->res_uv_]) * 100;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// If there are more modes to read then begin the next
|
// After the sensor integration time do the following
|
||||||
// otherwise stop
|
this->set_timeout(int_time + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME, [this, mode_index]() {
|
||||||
if (mode_index + 1 < (int) this->mode_funcs_.size()) {
|
// Read from the sensor
|
||||||
this->read_mode_(mode_index + 1);
|
std::get<1>(this->mode_funcs_[mode_index])();
|
||||||
} else {
|
|
||||||
// put sensor in standby
|
// If there are more modes to read then begin the next
|
||||||
std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get();
|
// otherwise stop
|
||||||
ctrl[LTR390_CTRL_EN] = false;
|
if (mode_index + 1 < (int) this->mode_funcs_.size()) {
|
||||||
this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong();
|
this->read_mode_(mode_index + 1);
|
||||||
this->reading_ = false;
|
} else {
|
||||||
}
|
// put sensor in standby
|
||||||
});
|
std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get();
|
||||||
|
ctrl[LTR390_CTRL_EN] = false;
|
||||||
|
this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong();
|
||||||
|
this->reading_ = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void LTR390Component::setup() {
|
void LTR390Component::setup() {
|
||||||
|
@ -151,16 +166,10 @@ void LTR390Component::setup() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set gain
|
|
||||||
this->reg(LTR390_GAIN) = gain_;
|
|
||||||
|
|
||||||
// Set resolution and measurement rate
|
|
||||||
this->reg(LTR390_MEAS_RATE) = RESOLUTION_SETTING[this->res_];
|
|
||||||
|
|
||||||
// Set sensitivity by linearly scaling against known value in the datasheet
|
// Set sensitivity by linearly scaling against known value in the datasheet
|
||||||
float gain_scale = GAINVALUES[this->gain_] / GAIN_MAX;
|
float gain_scale_uv = GAINVALUES[this->gain_uv_] / GAIN_MAX;
|
||||||
float intg_scale = (RESOLUTIONVALUE[this->res_] * 100) / INTG_MAX;
|
float intg_scale_uv = (RESOLUTIONVALUE[this->res_uv_] * 100) / INTG_MAX;
|
||||||
this->sensitivity_ = SENSITIVITY_MAX * gain_scale * intg_scale;
|
this->sensitivity_uv_ = SENSITIVITY_MAX * gain_scale_uv * intg_scale_uv;
|
||||||
|
|
||||||
// Set sensor read state
|
// Set sensor read state
|
||||||
this->reading_ = false;
|
this->reading_ = false;
|
||||||
|
@ -176,7 +185,13 @@ void LTR390Component::setup() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LTR390Component::dump_config() { LOG_I2C_DEVICE(this); }
|
void LTR390Component::dump_config() {
|
||||||
|
LOG_I2C_DEVICE(this);
|
||||||
|
ESP_LOGCONFIG(TAG, " ALS Gain: X%.0f", GAINVALUES[this->gain_als_]);
|
||||||
|
ESP_LOGCONFIG(TAG, " ALS Resolution: %u-bit", RESOLUTION_BITS[this->res_als_]);
|
||||||
|
ESP_LOGCONFIG(TAG, " UV Gain: X%.0f", GAINVALUES[this->gain_uv_]);
|
||||||
|
ESP_LOGCONFIG(TAG, " UV Resolution: %u-bit", RESOLUTION_BITS[this->res_uv_]);
|
||||||
|
}
|
||||||
|
|
||||||
void LTR390Component::update() {
|
void LTR390Component::update() {
|
||||||
if (!this->reading_ && !mode_funcs_.empty()) {
|
if (!this->reading_ && !mode_funcs_.empty()) {
|
||||||
|
|
|
@ -49,8 +49,10 @@ class LTR390Component : public PollingComponent, public i2c::I2CDevice {
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
void set_gain_value(LTR390GAIN gain) { this->gain_ = gain; }
|
void set_als_gain_value(LTR390GAIN gain) { this->gain_als_ = gain; }
|
||||||
void set_res_value(LTR390RESOLUTION res) { this->res_ = res; }
|
void set_uv_gain_value(LTR390GAIN gain) { this->gain_uv_ = gain; }
|
||||||
|
void set_als_res_value(LTR390RESOLUTION res) { this->res_als_ = res; }
|
||||||
|
void set_uv_res_value(LTR390RESOLUTION res) { this->res_uv_ = res; }
|
||||||
void set_wfac_value(float wfac) { this->wfac_ = wfac; }
|
void set_wfac_value(float wfac) { this->wfac_ = wfac; }
|
||||||
|
|
||||||
void set_light_sensor(sensor::Sensor *light_sensor) { this->light_sensor_ = light_sensor; }
|
void set_light_sensor(sensor::Sensor *light_sensor) { this->light_sensor_ = light_sensor; }
|
||||||
|
@ -71,9 +73,11 @@ class LTR390Component : public PollingComponent, public i2c::I2CDevice {
|
||||||
// a list of modes and corresponding read functions
|
// a list of modes and corresponding read functions
|
||||||
std::vector<std::tuple<LTR390MODE, std::function<void()>>> mode_funcs_;
|
std::vector<std::tuple<LTR390MODE, std::function<void()>>> mode_funcs_;
|
||||||
|
|
||||||
LTR390GAIN gain_;
|
LTR390GAIN gain_als_;
|
||||||
LTR390RESOLUTION res_;
|
LTR390GAIN gain_uv_;
|
||||||
float sensitivity_;
|
LTR390RESOLUTION res_als_;
|
||||||
|
LTR390RESOLUTION res_uv_;
|
||||||
|
float sensitivity_uv_;
|
||||||
float wfac_;
|
float wfac_;
|
||||||
|
|
||||||
sensor::Sensor *light_sensor_{nullptr};
|
sensor::Sensor *light_sensor_{nullptr};
|
||||||
|
|
|
@ -13,7 +13,7 @@ from esphome.const import (
|
||||||
UNIT_LUX,
|
UNIT_LUX,
|
||||||
)
|
)
|
||||||
|
|
||||||
CODEOWNERS = ["@sjtrny"]
|
CODEOWNERS = ["@sjtrny", "@latonita"]
|
||||||
DEPENDENCIES = ["i2c"]
|
DEPENDENCIES = ["i2c"]
|
||||||
|
|
||||||
ltr390_ns = cg.esphome_ns.namespace("ltr390")
|
ltr390_ns = cg.esphome_ns.namespace("ltr390")
|
||||||
|
@ -76,8 +76,24 @@ CONFIG_SCHEMA = cv.All(
|
||||||
accuracy_decimals=1,
|
accuracy_decimals=1,
|
||||||
device_class=DEVICE_CLASS_EMPTY,
|
device_class=DEVICE_CLASS_EMPTY,
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_GAIN, default="X18"): cv.enum(GAIN_OPTIONS),
|
cv.Optional(CONF_GAIN, default="X18"): cv.Any(
|
||||||
cv.Optional(CONF_RESOLUTION, default=20): cv.enum(RES_OPTIONS),
|
cv.enum(GAIN_OPTIONS),
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_AMBIENT_LIGHT): cv.enum(GAIN_OPTIONS),
|
||||||
|
cv.Required(CONF_UV): cv.enum(GAIN_OPTIONS),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_RESOLUTION, default=20): cv.Any(
|
||||||
|
cv.enum(RES_OPTIONS),
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_AMBIENT_LIGHT): cv.enum(RES_OPTIONS),
|
||||||
|
cv.Required(CONF_UV): cv.enum(RES_OPTIONS),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
),
|
||||||
cv.Optional(CONF_WINDOW_CORRECTION_FACTOR, default=1.0): cv.float_range(
|
cv.Optional(CONF_WINDOW_CORRECTION_FACTOR, default=1.0): cv.float_range(
|
||||||
min=1.0
|
min=1.0
|
||||||
),
|
),
|
||||||
|
@ -101,11 +117,25 @@ async def to_code(config):
|
||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
await i2c.register_i2c_device(var, config)
|
await i2c.register_i2c_device(var, config)
|
||||||
|
|
||||||
cg.add(var.set_gain_value(config[CONF_GAIN]))
|
|
||||||
cg.add(var.set_res_value(config[CONF_RESOLUTION]))
|
|
||||||
cg.add(var.set_wfac_value(config[CONF_WINDOW_CORRECTION_FACTOR]))
|
cg.add(var.set_wfac_value(config[CONF_WINDOW_CORRECTION_FACTOR]))
|
||||||
|
|
||||||
for key, funcName in TYPES.items():
|
for key, funcName in TYPES.items():
|
||||||
if key in config:
|
if key in config:
|
||||||
sens = await sensor.new_sensor(config[key])
|
sens = await sensor.new_sensor(config[key])
|
||||||
cg.add(getattr(var, funcName)(sens))
|
cg.add(getattr(var, funcName)(sens))
|
||||||
|
|
||||||
|
gain_value = config[CONF_GAIN]
|
||||||
|
if isinstance(gain_value, dict):
|
||||||
|
cg.add(var.set_als_gain_value(gain_value[CONF_AMBIENT_LIGHT]))
|
||||||
|
cg.add(var.set_uv_gain_value(gain_value[CONF_UV]))
|
||||||
|
else:
|
||||||
|
cg.add(var.set_als_gain_value(gain_value))
|
||||||
|
cg.add(var.set_uv_gain_value(gain_value))
|
||||||
|
|
||||||
|
res_value = config[CONF_RESOLUTION]
|
||||||
|
if isinstance(res_value, dict):
|
||||||
|
cg.add(var.set_als_res_value(res_value[CONF_AMBIENT_LIGHT]))
|
||||||
|
cg.add(var.set_uv_res_value(res_value[CONF_UV]))
|
||||||
|
else:
|
||||||
|
cg.add(var.set_als_res_value(res_value))
|
||||||
|
cg.add(var.set_uv_res_value(res_value))
|
||||||
|
|
|
@ -357,7 +357,9 @@ CONFIG_SCHEMA = cv.All(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(MicroWakeWord),
|
cv.GenerateID(): cv.declare_id(MicroWakeWord),
|
||||||
cv.GenerateID(CONF_MICROPHONE): cv.use_id(microphone.Microphone),
|
cv.GenerateID(CONF_MICROPHONE): cv.use_id(microphone.Microphone),
|
||||||
cv.Required(CONF_MODELS): cv.ensure_list(MODEL_SCHEMA),
|
cv.Required(CONF_MODELS): cv.ensure_list(
|
||||||
|
cv.maybe_simple_value(MODEL_SCHEMA, key=CONF_MODEL)
|
||||||
|
),
|
||||||
cv.Optional(CONF_ON_WAKE_WORD_DETECTED): automation.validate_automation(
|
cv.Optional(CONF_ON_WAKE_WORD_DETECTED): automation.validate_automation(
|
||||||
single=True
|
single=True
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
|
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
|
||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
#include "ota_backend_arduino_esp32.h"
|
|
||||||
#include "ota_backend.h"
|
#include "ota_backend.h"
|
||||||
|
#include "ota_backend_arduino_esp32.h"
|
||||||
|
|
||||||
#include <Update.h>
|
#include <Update.h>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ota {
|
namespace ota {
|
||||||
|
|
||||||
|
static const char *const TAG = "ota.arduino_esp32";
|
||||||
|
|
||||||
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoESP32OTABackend>(); }
|
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoESP32OTABackend>(); }
|
||||||
|
|
||||||
OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) {
|
OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) {
|
||||||
|
@ -20,6 +23,9 @@ OTAResponseTypes ArduinoESP32OTABackend::begin(size_t image_size) {
|
||||||
uint8_t error = Update.getError();
|
uint8_t error = Update.getError();
|
||||||
if (error == UPDATE_ERROR_SIZE)
|
if (error == UPDATE_ERROR_SIZE)
|
||||||
return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE;
|
return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE;
|
||||||
|
|
||||||
|
ESP_LOGE(TAG, "Begin error: %d", error);
|
||||||
|
|
||||||
return OTA_RESPONSE_ERROR_UNKNOWN;
|
return OTA_RESPONSE_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,16 +33,25 @@ void ArduinoESP32OTABackend::set_update_md5(const char *md5) { Update.setMD5(md5
|
||||||
|
|
||||||
OTAResponseTypes ArduinoESP32OTABackend::write(uint8_t *data, size_t len) {
|
OTAResponseTypes ArduinoESP32OTABackend::write(uint8_t *data, size_t len) {
|
||||||
size_t written = Update.write(data, len);
|
size_t written = Update.write(data, len);
|
||||||
if (written != len) {
|
if (written == len) {
|
||||||
return OTA_RESPONSE_ERROR_WRITING_FLASH;
|
return OTA_RESPONSE_OK;
|
||||||
}
|
}
|
||||||
return OTA_RESPONSE_OK;
|
|
||||||
|
uint8_t error = Update.getError();
|
||||||
|
ESP_LOGE(TAG, "Write error: %d", error);
|
||||||
|
|
||||||
|
return OTA_RESPONSE_ERROR_WRITING_FLASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
OTAResponseTypes ArduinoESP32OTABackend::end() {
|
OTAResponseTypes ArduinoESP32OTABackend::end() {
|
||||||
if (!Update.end())
|
if (Update.end()) {
|
||||||
return OTA_RESPONSE_ERROR_UPDATE_END;
|
return OTA_RESPONSE_OK;
|
||||||
return OTA_RESPONSE_OK;
|
}
|
||||||
|
|
||||||
|
uint8_t error = Update.getError();
|
||||||
|
ESP_LOGE(TAG, "End error: %d", error);
|
||||||
|
|
||||||
|
return OTA_RESPONSE_ERROR_UPDATE_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArduinoESP32OTABackend::abort() { Update.abort(); }
|
void ArduinoESP32OTABackend::abort() { Update.abort(); }
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
#ifdef USE_ESP8266
|
#ifdef USE_ESP8266
|
||||||
#include "ota_backend.h"
|
|
||||||
#include "ota_backend_arduino_esp8266.h"
|
#include "ota_backend_arduino_esp8266.h"
|
||||||
|
#include "ota_backend.h"
|
||||||
|
|
||||||
#include "esphome/core/defines.h"
|
|
||||||
#include "esphome/components/esp8266/preferences.h"
|
#include "esphome/components/esp8266/preferences.h"
|
||||||
|
#include "esphome/core/defines.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
#include <Updater.h>
|
#include <Updater.h>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ota {
|
namespace ota {
|
||||||
|
|
||||||
|
static const char *const TAG = "ota.arduino_esp8266";
|
||||||
|
|
||||||
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoESP8266OTABackend>(); }
|
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoESP8266OTABackend>(); }
|
||||||
|
|
||||||
OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) {
|
OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) {
|
||||||
|
@ -29,6 +32,9 @@ OTAResponseTypes ArduinoESP8266OTABackend::begin(size_t image_size) {
|
||||||
return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG;
|
return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG;
|
||||||
if (error == UPDATE_ERROR_SPACE)
|
if (error == UPDATE_ERROR_SPACE)
|
||||||
return OTA_RESPONSE_ERROR_ESP8266_NOT_ENOUGH_SPACE;
|
return OTA_RESPONSE_ERROR_ESP8266_NOT_ENOUGH_SPACE;
|
||||||
|
|
||||||
|
ESP_LOGE(TAG, "Begin error: %d", error);
|
||||||
|
|
||||||
return OTA_RESPONSE_ERROR_UNKNOWN;
|
return OTA_RESPONSE_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,16 +42,25 @@ void ArduinoESP8266OTABackend::set_update_md5(const char *md5) { Update.setMD5(m
|
||||||
|
|
||||||
OTAResponseTypes ArduinoESP8266OTABackend::write(uint8_t *data, size_t len) {
|
OTAResponseTypes ArduinoESP8266OTABackend::write(uint8_t *data, size_t len) {
|
||||||
size_t written = Update.write(data, len);
|
size_t written = Update.write(data, len);
|
||||||
if (written != len) {
|
if (written == len) {
|
||||||
return OTA_RESPONSE_ERROR_WRITING_FLASH;
|
return OTA_RESPONSE_OK;
|
||||||
}
|
}
|
||||||
return OTA_RESPONSE_OK;
|
|
||||||
|
uint8_t error = Update.getError();
|
||||||
|
ESP_LOGE(TAG, "Write error: %d", error);
|
||||||
|
|
||||||
|
return OTA_RESPONSE_ERROR_WRITING_FLASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
OTAResponseTypes ArduinoESP8266OTABackend::end() {
|
OTAResponseTypes ArduinoESP8266OTABackend::end() {
|
||||||
if (!Update.end())
|
if (Update.end()) {
|
||||||
return OTA_RESPONSE_ERROR_UPDATE_END;
|
return OTA_RESPONSE_OK;
|
||||||
return OTA_RESPONSE_OK;
|
}
|
||||||
|
|
||||||
|
uint8_t error = Update.getError();
|
||||||
|
ESP_LOGE(TAG, "End error: %d", error);
|
||||||
|
|
||||||
|
return OTA_RESPONSE_ERROR_UPDATE_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArduinoESP8266OTABackend::abort() {
|
void ArduinoESP8266OTABackend::abort() {
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
#ifdef USE_LIBRETINY
|
#ifdef USE_LIBRETINY
|
||||||
#include "ota_backend.h"
|
|
||||||
#include "ota_backend_arduino_libretiny.h"
|
#include "ota_backend_arduino_libretiny.h"
|
||||||
|
#include "ota_backend.h"
|
||||||
|
|
||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
#include <Update.h>
|
#include <Update.h>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ota {
|
namespace ota {
|
||||||
|
|
||||||
|
static const char *const TAG = "ota.arduino_libretiny";
|
||||||
|
|
||||||
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoLibreTinyOTABackend>(); }
|
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoLibreTinyOTABackend>(); }
|
||||||
|
|
||||||
OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) {
|
OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) {
|
||||||
|
@ -20,6 +23,9 @@ OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) {
|
||||||
uint8_t error = Update.getError();
|
uint8_t error = Update.getError();
|
||||||
if (error == UPDATE_ERROR_SIZE)
|
if (error == UPDATE_ERROR_SIZE)
|
||||||
return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE;
|
return OTA_RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE;
|
||||||
|
|
||||||
|
ESP_LOGE(TAG, "Begin error: %d", error);
|
||||||
|
|
||||||
return OTA_RESPONSE_ERROR_UNKNOWN;
|
return OTA_RESPONSE_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,16 +33,25 @@ void ArduinoLibreTinyOTABackend::set_update_md5(const char *md5) { Update.setMD5
|
||||||
|
|
||||||
OTAResponseTypes ArduinoLibreTinyOTABackend::write(uint8_t *data, size_t len) {
|
OTAResponseTypes ArduinoLibreTinyOTABackend::write(uint8_t *data, size_t len) {
|
||||||
size_t written = Update.write(data, len);
|
size_t written = Update.write(data, len);
|
||||||
if (written != len) {
|
if (written == len) {
|
||||||
return OTA_RESPONSE_ERROR_WRITING_FLASH;
|
return OTA_RESPONSE_OK;
|
||||||
}
|
}
|
||||||
return OTA_RESPONSE_OK;
|
|
||||||
|
uint8_t error = Update.getError();
|
||||||
|
ESP_LOGE(TAG, "Write error: %d", error);
|
||||||
|
|
||||||
|
return OTA_RESPONSE_ERROR_WRITING_FLASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
OTAResponseTypes ArduinoLibreTinyOTABackend::end() {
|
OTAResponseTypes ArduinoLibreTinyOTABackend::end() {
|
||||||
if (!Update.end())
|
if (Update.end()) {
|
||||||
return OTA_RESPONSE_ERROR_UPDATE_END;
|
return OTA_RESPONSE_OK;
|
||||||
return OTA_RESPONSE_OK;
|
}
|
||||||
|
|
||||||
|
uint8_t error = Update.getError();
|
||||||
|
ESP_LOGE(TAG, "End error: %d", error);
|
||||||
|
|
||||||
|
return OTA_RESPONSE_ERROR_UPDATE_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArduinoLibreTinyOTABackend::abort() { Update.abort(); }
|
void ArduinoLibreTinyOTABackend::abort() { Update.abort(); }
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
#ifdef USE_RP2040
|
#ifdef USE_RP2040
|
||||||
#include "ota_backend.h"
|
|
||||||
#include "ota_backend_arduino_rp2040.h"
|
#include "ota_backend_arduino_rp2040.h"
|
||||||
|
#include "ota_backend.h"
|
||||||
|
|
||||||
#include "esphome/components/rp2040/preferences.h"
|
#include "esphome/components/rp2040/preferences.h"
|
||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
#include <Updater.h>
|
#include <Updater.h>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ota {
|
namespace ota {
|
||||||
|
|
||||||
|
static const char *const TAG = "ota.arduino_rp2040";
|
||||||
|
|
||||||
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoRP2040OTABackend>(); }
|
std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoRP2040OTABackend>(); }
|
||||||
|
|
||||||
OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) {
|
OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) {
|
||||||
|
@ -29,6 +32,9 @@ OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) {
|
||||||
return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG;
|
return OTA_RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG;
|
||||||
if (error == UPDATE_ERROR_SPACE)
|
if (error == UPDATE_ERROR_SPACE)
|
||||||
return OTA_RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE;
|
return OTA_RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE;
|
||||||
|
|
||||||
|
ESP_LOGE(TAG, "Begin error: %d", error);
|
||||||
|
|
||||||
return OTA_RESPONSE_ERROR_UNKNOWN;
|
return OTA_RESPONSE_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,16 +42,25 @@ void ArduinoRP2040OTABackend::set_update_md5(const char *md5) { Update.setMD5(md
|
||||||
|
|
||||||
OTAResponseTypes ArduinoRP2040OTABackend::write(uint8_t *data, size_t len) {
|
OTAResponseTypes ArduinoRP2040OTABackend::write(uint8_t *data, size_t len) {
|
||||||
size_t written = Update.write(data, len);
|
size_t written = Update.write(data, len);
|
||||||
if (written != len) {
|
if (written == len) {
|
||||||
return OTA_RESPONSE_ERROR_WRITING_FLASH;
|
return OTA_RESPONSE_OK;
|
||||||
}
|
}
|
||||||
return OTA_RESPONSE_OK;
|
|
||||||
|
uint8_t error = Update.getError();
|
||||||
|
ESP_LOGE(TAG, "Write error: %d", error);
|
||||||
|
|
||||||
|
return OTA_RESPONSE_ERROR_WRITING_FLASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
OTAResponseTypes ArduinoRP2040OTABackend::end() {
|
OTAResponseTypes ArduinoRP2040OTABackend::end() {
|
||||||
if (!Update.end())
|
if (Update.end()) {
|
||||||
return OTA_RESPONSE_ERROR_UPDATE_END;
|
return OTA_RESPONSE_OK;
|
||||||
return OTA_RESPONSE_OK;
|
}
|
||||||
|
|
||||||
|
uint8_t error = Update.getError();
|
||||||
|
ESP_LOGE(TAG, "End error: %d", error);
|
||||||
|
|
||||||
|
return OTA_RESPONSE_ERROR_UPDATE_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArduinoRP2040OTABackend::abort() {
|
void ArduinoRP2040OTABackend::abort() {
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
#ifndef __linux__
|
#if !(defined(__linux__) || defined(__APPLE__))
|
||||||
#error This HostUartComponent implementation is only for Linux
|
#error This HostUartComponent implementation is not supported on this host OS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -24,6 +24,9 @@
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
speed_t get_baud(int baud) {
|
speed_t get_baud(int baud) {
|
||||||
|
#ifdef __APPLE__
|
||||||
|
return baud;
|
||||||
|
#else
|
||||||
switch (baud) {
|
switch (baud) {
|
||||||
case 50:
|
case 50:
|
||||||
return B50;
|
return B50;
|
||||||
|
@ -88,6 +91,7 @@ speed_t get_baud(int baud) {
|
||||||
default:
|
default:
|
||||||
return B0;
|
return B0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -46,29 +46,6 @@ static const char *const HEADER_CORS_REQ_PNA = "Access-Control-Request-Private-N
|
||||||
static const char *const HEADER_CORS_ALLOW_PNA = "Access-Control-Allow-Private-Network";
|
static const char *const HEADER_CORS_ALLOW_PNA = "Access-Control-Allow-Private-Network";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_WEBSERVER_VERSION == 1
|
|
||||||
void write_row(AsyncResponseStream *stream, EntityBase *obj, const std::string &klass, const std::string &action,
|
|
||||||
const std::function<void(AsyncResponseStream &stream, EntityBase *obj)> &action_func = nullptr) {
|
|
||||||
stream->print("<tr class=\"");
|
|
||||||
stream->print(klass.c_str());
|
|
||||||
if (obj->is_internal())
|
|
||||||
stream->print(" internal");
|
|
||||||
stream->print("\" id=\"");
|
|
||||||
stream->print(klass.c_str());
|
|
||||||
stream->print("-");
|
|
||||||
stream->print(obj->get_object_id().c_str());
|
|
||||||
stream->print("\"><td>");
|
|
||||||
stream->print(obj->get_name().c_str());
|
|
||||||
stream->print("</td><td></td><td>");
|
|
||||||
stream->print(action.c_str());
|
|
||||||
if (action_func) {
|
|
||||||
action_func(*stream, obj);
|
|
||||||
}
|
|
||||||
stream->print("</td>");
|
|
||||||
stream->print("</tr>");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
UrlMatch match_url(const std::string &url, bool only_domain = false) {
|
UrlMatch match_url(const std::string &url, bool only_domain = false) {
|
||||||
UrlMatch match;
|
UrlMatch match;
|
||||||
match.valid = false;
|
match.valid = false;
|
||||||
|
@ -102,11 +79,6 @@ WebServer::WebServer(web_server_base::WebServerBase *base)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USE_WEBSERVER_VERSION == 1
|
|
||||||
void WebServer::set_css_url(const char *css_url) { this->css_url_ = css_url; }
|
|
||||||
void WebServer::set_js_url(const char *js_url) { this->js_url_ = js_url; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_WEBSERVER_CSS_INCLUDE
|
#ifdef USE_WEBSERVER_CSS_INCLUDE
|
||||||
void WebServer::set_css_include(const char *css_include) { this->css_include_ = css_include; }
|
void WebServer::set_css_include(const char *css_include) { this->css_include_ = css_include; }
|
||||||
#endif
|
#endif
|
||||||
|
@ -181,187 +153,6 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) {
|
||||||
response->addHeader("Content-Encoding", "gzip");
|
response->addHeader("Content-Encoding", "gzip");
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
#elif USE_WEBSERVER_VERSION == 1
|
|
||||||
void WebServer::handle_index_request(AsyncWebServerRequest *request) {
|
|
||||||
AsyncResponseStream *stream = request->beginResponseStream("text/html");
|
|
||||||
const std::string &title = App.get_name();
|
|
||||||
stream->print(F("<!DOCTYPE html><html lang=\"en\"><head><meta charset=UTF-8><meta "
|
|
||||||
"name=viewport content=\"width=device-width, initial-scale=1,user-scalable=no\"><title>"));
|
|
||||||
stream->print(title.c_str());
|
|
||||||
stream->print(F("</title>"));
|
|
||||||
#ifdef USE_WEBSERVER_CSS_INCLUDE
|
|
||||||
stream->print(F("<link rel=\"stylesheet\" href=\"/0.css\">"));
|
|
||||||
#endif
|
|
||||||
if (strlen(this->css_url_) > 0) {
|
|
||||||
stream->print(F(R"(<link rel="stylesheet" href=")"));
|
|
||||||
stream->print(this->css_url_);
|
|
||||||
stream->print(F("\">"));
|
|
||||||
}
|
|
||||||
stream->print(F("</head><body>"));
|
|
||||||
stream->print(F("<article class=\"markdown-body\"><h1>"));
|
|
||||||
stream->print(title.c_str());
|
|
||||||
stream->print(F("</h1>"));
|
|
||||||
stream->print(F("<h2>States</h2><table id=\"states\"><thead><tr><th>Name<th>State<th>Actions<tbody>"));
|
|
||||||
|
|
||||||
#ifdef USE_SENSOR
|
|
||||||
for (auto *obj : App.get_sensors()) {
|
|
||||||
if (this->include_internal_ || !obj->is_internal())
|
|
||||||
write_row(stream, obj, "sensor", "");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_SWITCH
|
|
||||||
for (auto *obj : App.get_switches()) {
|
|
||||||
if (this->include_internal_ || !obj->is_internal())
|
|
||||||
write_row(stream, obj, "switch", "<button>Toggle</button>");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_BUTTON
|
|
||||||
for (auto *obj : App.get_buttons())
|
|
||||||
write_row(stream, obj, "button", "<button>Press</button>");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_BINARY_SENSOR
|
|
||||||
for (auto *obj : App.get_binary_sensors()) {
|
|
||||||
if (this->include_internal_ || !obj->is_internal())
|
|
||||||
write_row(stream, obj, "binary_sensor", "");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_FAN
|
|
||||||
for (auto *obj : App.get_fans()) {
|
|
||||||
if (this->include_internal_ || !obj->is_internal())
|
|
||||||
write_row(stream, obj, "fan", "<button>Toggle</button>");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_LIGHT
|
|
||||||
for (auto *obj : App.get_lights()) {
|
|
||||||
if (this->include_internal_ || !obj->is_internal())
|
|
||||||
write_row(stream, obj, "light", "<button>Toggle</button>");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_TEXT_SENSOR
|
|
||||||
for (auto *obj : App.get_text_sensors()) {
|
|
||||||
if (this->include_internal_ || !obj->is_internal())
|
|
||||||
write_row(stream, obj, "text_sensor", "");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_COVER
|
|
||||||
for (auto *obj : App.get_covers()) {
|
|
||||||
if (this->include_internal_ || !obj->is_internal())
|
|
||||||
write_row(stream, obj, "cover", "<button>Open</button><button>Close</button>");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_NUMBER
|
|
||||||
for (auto *obj : App.get_numbers()) {
|
|
||||||
if (this->include_internal_ || !obj->is_internal()) {
|
|
||||||
write_row(stream, obj, "number", "", [](AsyncResponseStream &stream, EntityBase *obj) {
|
|
||||||
number::Number *number = (number::Number *) obj;
|
|
||||||
stream.print(R"(<input type="number" min=")");
|
|
||||||
stream.print(number->traits.get_min_value());
|
|
||||||
stream.print(R"(" max=")");
|
|
||||||
stream.print(number->traits.get_max_value());
|
|
||||||
stream.print(R"(" step=")");
|
|
||||||
stream.print(number->traits.get_step());
|
|
||||||
stream.print(R"(" value=")");
|
|
||||||
stream.print(number->state);
|
|
||||||
stream.print(R"("/>)");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_TEXT
|
|
||||||
for (auto *obj : App.get_texts()) {
|
|
||||||
if (this->include_internal_ || !obj->is_internal()) {
|
|
||||||
write_row(stream, obj, "text", "", [](AsyncResponseStream &stream, EntityBase *obj) {
|
|
||||||
text::Text *text = (text::Text *) obj;
|
|
||||||
auto mode = (int) text->traits.get_mode();
|
|
||||||
stream.print(R"(<input type=")");
|
|
||||||
if (mode == 2) {
|
|
||||||
stream.print(R"(password)");
|
|
||||||
} else { // default
|
|
||||||
stream.print(R"(text)");
|
|
||||||
}
|
|
||||||
stream.print(R"(" minlength=")");
|
|
||||||
stream.print(text->traits.get_min_length());
|
|
||||||
stream.print(R"(" maxlength=")");
|
|
||||||
stream.print(text->traits.get_max_length());
|
|
||||||
stream.print(R"(" pattern=")");
|
|
||||||
stream.print(text->traits.get_pattern().c_str());
|
|
||||||
stream.print(R"(" value=")");
|
|
||||||
stream.print(text->state.c_str());
|
|
||||||
stream.print(R"("/>)");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_SELECT
|
|
||||||
for (auto *obj : App.get_selects()) {
|
|
||||||
if (this->include_internal_ || !obj->is_internal()) {
|
|
||||||
write_row(stream, obj, "select", "", [](AsyncResponseStream &stream, EntityBase *obj) {
|
|
||||||
select::Select *select = (select::Select *) obj;
|
|
||||||
stream.print("<select>");
|
|
||||||
stream.print("<option></option>");
|
|
||||||
for (auto const &option : select->traits.get_options()) {
|
|
||||||
stream.print("<option>");
|
|
||||||
stream.print(option.c_str());
|
|
||||||
stream.print("</option>");
|
|
||||||
}
|
|
||||||
stream.print("</select>");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_LOCK
|
|
||||||
for (auto *obj : App.get_locks()) {
|
|
||||||
if (this->include_internal_ || !obj->is_internal()) {
|
|
||||||
write_row(stream, obj, "lock", "", [](AsyncResponseStream &stream, EntityBase *obj) {
|
|
||||||
lock::Lock *lock = (lock::Lock *) obj;
|
|
||||||
stream.print("<button>Lock</button><button>Unlock</button>");
|
|
||||||
if (lock->traits.get_supports_open()) {
|
|
||||||
stream.print("<button>Open</button>");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_CLIMATE
|
|
||||||
for (auto *obj : App.get_climates()) {
|
|
||||||
if (this->include_internal_ || !obj->is_internal())
|
|
||||||
write_row(stream, obj, "climate", "");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stream->print(F("</tbody></table><p>See <a href=\"https://esphome.io/web-api/index.html\">ESPHome Web API</a> for "
|
|
||||||
"REST API documentation.</p>"));
|
|
||||||
if (this->allow_ota_) {
|
|
||||||
stream->print(
|
|
||||||
F("<h2>OTA Update</h2><form method=\"POST\" action=\"/update\" enctype=\"multipart/form-data\"><input "
|
|
||||||
"type=\"file\" name=\"update\"><input type=\"submit\" value=\"Update\"></form>"));
|
|
||||||
}
|
|
||||||
stream->print(F("<h2>Debug Log</h2><pre id=\"log\"></pre>"));
|
|
||||||
#ifdef USE_WEBSERVER_JS_INCLUDE
|
|
||||||
if (this->js_include_ != nullptr) {
|
|
||||||
stream->print(F("<script type=\"module\" src=\"/0.js\"></script>"));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (strlen(this->js_url_) > 0) {
|
|
||||||
stream->print(F("<script src=\""));
|
|
||||||
stream->print(this->js_url_);
|
|
||||||
stream->print(F("\"></script>"));
|
|
||||||
}
|
|
||||||
stream->print(F("</article></body></html>"));
|
|
||||||
request->send(stream);
|
|
||||||
}
|
|
||||||
#elif USE_WEBSERVER_VERSION >= 2
|
#elif USE_WEBSERVER_VERSION >= 2
|
||||||
void WebServer::handle_index_request(AsyncWebServerRequest *request) {
|
void WebServer::handle_index_request(AsyncWebServerRequest *request) {
|
||||||
AsyncWebServerResponse *response =
|
AsyncWebServerResponse *response =
|
||||||
|
|
217
esphome/components/web_server/web_server_v1.cpp
Normal file
217
esphome/components/web_server/web_server_v1.cpp
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
#include "web_server.h"
|
||||||
|
#include "esphome/core/application.h"
|
||||||
|
|
||||||
|
#if USE_WEBSERVER_VERSION == 1
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace web_server {
|
||||||
|
|
||||||
|
void write_row(AsyncResponseStream *stream, EntityBase *obj, const std::string &klass, const std::string &action,
|
||||||
|
const std::function<void(AsyncResponseStream &stream, EntityBase *obj)> &action_func = nullptr) {
|
||||||
|
stream->print("<tr class=\"");
|
||||||
|
stream->print(klass.c_str());
|
||||||
|
if (obj->is_internal())
|
||||||
|
stream->print(" internal");
|
||||||
|
stream->print("\" id=\"");
|
||||||
|
stream->print(klass.c_str());
|
||||||
|
stream->print("-");
|
||||||
|
stream->print(obj->get_object_id().c_str());
|
||||||
|
stream->print("\"><td>");
|
||||||
|
stream->print(obj->get_name().c_str());
|
||||||
|
stream->print("</td><td></td><td>");
|
||||||
|
stream->print(action.c_str());
|
||||||
|
if (action_func) {
|
||||||
|
action_func(*stream, obj);
|
||||||
|
}
|
||||||
|
stream->print("</td>");
|
||||||
|
stream->print("</tr>");
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebServer::set_css_url(const char *css_url) { this->css_url_ = css_url; }
|
||||||
|
|
||||||
|
void WebServer::set_js_url(const char *js_url) { this->js_url_ = js_url; }
|
||||||
|
|
||||||
|
void WebServer::handle_index_request(AsyncWebServerRequest *request) {
|
||||||
|
AsyncResponseStream *stream = request->beginResponseStream("text/html");
|
||||||
|
const std::string &title = App.get_name();
|
||||||
|
stream->print(F("<!DOCTYPE html><html lang=\"en\"><head><meta charset=UTF-8><meta "
|
||||||
|
"name=viewport content=\"width=device-width, initial-scale=1,user-scalable=no\"><title>"));
|
||||||
|
stream->print(title.c_str());
|
||||||
|
stream->print(F("</title>"));
|
||||||
|
#ifdef USE_WEBSERVER_CSS_INCLUDE
|
||||||
|
stream->print(F("<link rel=\"stylesheet\" href=\"/0.css\">"));
|
||||||
|
#endif
|
||||||
|
if (strlen(this->css_url_) > 0) {
|
||||||
|
stream->print(F(R"(<link rel="stylesheet" href=")"));
|
||||||
|
stream->print(this->css_url_);
|
||||||
|
stream->print(F("\">"));
|
||||||
|
}
|
||||||
|
stream->print(F("</head><body>"));
|
||||||
|
stream->print(F("<article class=\"markdown-body\"><h1>"));
|
||||||
|
stream->print(title.c_str());
|
||||||
|
stream->print(F("</h1>"));
|
||||||
|
stream->print(F("<h2>States</h2><table id=\"states\"><thead><tr><th>Name<th>State<th>Actions<tbody>"));
|
||||||
|
|
||||||
|
#ifdef USE_SENSOR
|
||||||
|
for (auto *obj : App.get_sensors()) {
|
||||||
|
if (this->include_internal_ || !obj->is_internal())
|
||||||
|
write_row(stream, obj, "sensor", "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_SWITCH
|
||||||
|
for (auto *obj : App.get_switches()) {
|
||||||
|
if (this->include_internal_ || !obj->is_internal())
|
||||||
|
write_row(stream, obj, "switch", "<button>Toggle</button>");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_BUTTON
|
||||||
|
for (auto *obj : App.get_buttons())
|
||||||
|
write_row(stream, obj, "button", "<button>Press</button>");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_BINARY_SENSOR
|
||||||
|
for (auto *obj : App.get_binary_sensors()) {
|
||||||
|
if (this->include_internal_ || !obj->is_internal())
|
||||||
|
write_row(stream, obj, "binary_sensor", "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_FAN
|
||||||
|
for (auto *obj : App.get_fans()) {
|
||||||
|
if (this->include_internal_ || !obj->is_internal())
|
||||||
|
write_row(stream, obj, "fan", "<button>Toggle</button>");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_LIGHT
|
||||||
|
for (auto *obj : App.get_lights()) {
|
||||||
|
if (this->include_internal_ || !obj->is_internal())
|
||||||
|
write_row(stream, obj, "light", "<button>Toggle</button>");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_TEXT_SENSOR
|
||||||
|
for (auto *obj : App.get_text_sensors()) {
|
||||||
|
if (this->include_internal_ || !obj->is_internal())
|
||||||
|
write_row(stream, obj, "text_sensor", "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_COVER
|
||||||
|
for (auto *obj : App.get_covers()) {
|
||||||
|
if (this->include_internal_ || !obj->is_internal())
|
||||||
|
write_row(stream, obj, "cover", "<button>Open</button><button>Close</button>");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_NUMBER
|
||||||
|
for (auto *obj : App.get_numbers()) {
|
||||||
|
if (this->include_internal_ || !obj->is_internal()) {
|
||||||
|
write_row(stream, obj, "number", "", [](AsyncResponseStream &stream, EntityBase *obj) {
|
||||||
|
number::Number *number = (number::Number *) obj;
|
||||||
|
stream.print(R"(<input type="number" min=")");
|
||||||
|
stream.print(number->traits.get_min_value());
|
||||||
|
stream.print(R"(" max=")");
|
||||||
|
stream.print(number->traits.get_max_value());
|
||||||
|
stream.print(R"(" step=")");
|
||||||
|
stream.print(number->traits.get_step());
|
||||||
|
stream.print(R"(" value=")");
|
||||||
|
stream.print(number->state);
|
||||||
|
stream.print(R"("/>)");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_TEXT
|
||||||
|
for (auto *obj : App.get_texts()) {
|
||||||
|
if (this->include_internal_ || !obj->is_internal()) {
|
||||||
|
write_row(stream, obj, "text", "", [](AsyncResponseStream &stream, EntityBase *obj) {
|
||||||
|
text::Text *text = (text::Text *) obj;
|
||||||
|
auto mode = (int) text->traits.get_mode();
|
||||||
|
stream.print(R"(<input type=")");
|
||||||
|
if (mode == 2) {
|
||||||
|
stream.print(R"(password)");
|
||||||
|
} else { // default
|
||||||
|
stream.print(R"(text)");
|
||||||
|
}
|
||||||
|
stream.print(R"(" minlength=")");
|
||||||
|
stream.print(text->traits.get_min_length());
|
||||||
|
stream.print(R"(" maxlength=")");
|
||||||
|
stream.print(text->traits.get_max_length());
|
||||||
|
stream.print(R"(" pattern=")");
|
||||||
|
stream.print(text->traits.get_pattern().c_str());
|
||||||
|
stream.print(R"(" value=")");
|
||||||
|
stream.print(text->state.c_str());
|
||||||
|
stream.print(R"("/>)");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_SELECT
|
||||||
|
for (auto *obj : App.get_selects()) {
|
||||||
|
if (this->include_internal_ || !obj->is_internal()) {
|
||||||
|
write_row(stream, obj, "select", "", [](AsyncResponseStream &stream, EntityBase *obj) {
|
||||||
|
select::Select *select = (select::Select *) obj;
|
||||||
|
stream.print("<select>");
|
||||||
|
stream.print("<option></option>");
|
||||||
|
for (auto const &option : select->traits.get_options()) {
|
||||||
|
stream.print("<option>");
|
||||||
|
stream.print(option.c_str());
|
||||||
|
stream.print("</option>");
|
||||||
|
}
|
||||||
|
stream.print("</select>");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_LOCK
|
||||||
|
for (auto *obj : App.get_locks()) {
|
||||||
|
if (this->include_internal_ || !obj->is_internal()) {
|
||||||
|
write_row(stream, obj, "lock", "", [](AsyncResponseStream &stream, EntityBase *obj) {
|
||||||
|
lock::Lock *lock = (lock::Lock *) obj;
|
||||||
|
stream.print("<button>Lock</button><button>Unlock</button>");
|
||||||
|
if (lock->traits.get_supports_open()) {
|
||||||
|
stream.print("<button>Open</button>");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_CLIMATE
|
||||||
|
for (auto *obj : App.get_climates()) {
|
||||||
|
if (this->include_internal_ || !obj->is_internal())
|
||||||
|
write_row(stream, obj, "climate", "");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
stream->print(F("</tbody></table><p>See <a href=\"https://esphome.io/web-api/index.html\">ESPHome Web API</a> for "
|
||||||
|
"REST API documentation.</p>"));
|
||||||
|
if (this->allow_ota_) {
|
||||||
|
stream->print(
|
||||||
|
F("<h2>OTA Update</h2><form method=\"POST\" action=\"/update\" enctype=\"multipart/form-data\"><input "
|
||||||
|
"type=\"file\" name=\"update\"><input type=\"submit\" value=\"Update\"></form>"));
|
||||||
|
}
|
||||||
|
stream->print(F("<h2>Debug Log</h2><pre id=\"log\"></pre>"));
|
||||||
|
#ifdef USE_WEBSERVER_JS_INCLUDE
|
||||||
|
if (this->js_include_ != nullptr) {
|
||||||
|
stream->print(F("<script type=\"module\" src=\"/0.js\"></script>"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (strlen(this->js_url_) > 0) {
|
||||||
|
stream->print(F("<script src=\""));
|
||||||
|
stream->print(this->js_url_);
|
||||||
|
stream->print(F("\"></script>"));
|
||||||
|
}
|
||||||
|
stream->print(F("</article></body></html>"));
|
||||||
|
request->send(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace web_server
|
||||||
|
} // namespace esphome
|
||||||
|
#endif
|
|
@ -82,8 +82,8 @@ bool WiFiComponent::wifi_mode_(optional<bool> sta, optional<bool> ap) {
|
||||||
|
|
||||||
// WiFiClass::mode above calls esp_netif_create_default_wifi_sta() and
|
// WiFiClass::mode above calls esp_netif_create_default_wifi_sta() and
|
||||||
// esp_netif_create_default_wifi_ap(), which creates the interfaces.
|
// esp_netif_create_default_wifi_ap(), which creates the interfaces.
|
||||||
if (set_sta)
|
// s_sta_netif handle is set during ESPHOME_EVENT_ID_WIFI_STA_START event
|
||||||
s_sta_netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
|
|
||||||
#ifdef USE_WIFI_AP
|
#ifdef USE_WIFI_AP
|
||||||
if (set_ap)
|
if (set_ap)
|
||||||
s_ap_netif = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF");
|
s_ap_netif = esp_netif_get_handle_from_ifkey("WIFI_AP_DEF");
|
||||||
|
@ -495,6 +495,7 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_
|
||||||
case ESPHOME_EVENT_ID_WIFI_STA_START: {
|
case ESPHOME_EVENT_ID_WIFI_STA_START: {
|
||||||
ESP_LOGV(TAG, "Event: WiFi STA start");
|
ESP_LOGV(TAG, "Event: WiFi STA start");
|
||||||
// apply hostname
|
// apply hostname
|
||||||
|
s_sta_netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
|
||||||
esp_err_t err = esp_netif_set_hostname(s_sta_netif, App.get_name().c_str());
|
esp_err_t err = esp_netif_set_hostname(s_sta_netif, App.get_name().c_str());
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err));
|
ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err));
|
||||||
|
|
|
@ -65,7 +65,7 @@ lib_deps =
|
||||||
glmnet/Dsmr@0.7 ; dsmr
|
glmnet/Dsmr@0.7 ; dsmr
|
||||||
rweather/Crypto@0.4.0 ; dsmr
|
rweather/Crypto@0.4.0 ; dsmr
|
||||||
dudanov/MideaUART@1.1.9 ; midea
|
dudanov/MideaUART@1.1.9 ; midea
|
||||||
tonia/HeatpumpIR@1.0.26 ; heatpumpir
|
tonia/HeatpumpIR@1.0.27 ; heatpumpir
|
||||||
build_flags =
|
build_flags =
|
||||||
${common.build_flags}
|
${common.build_flags}
|
||||||
-DUSE_ARDUINO
|
-DUSE_ARDUINO
|
||||||
|
@ -93,8 +93,8 @@ lib_deps =
|
||||||
ESP8266HTTPClient ; http_request (Arduino built-in)
|
ESP8266HTTPClient ; http_request (Arduino built-in)
|
||||||
ESP8266mDNS ; mdns (Arduino built-in)
|
ESP8266mDNS ; mdns (Arduino built-in)
|
||||||
DNSServer ; captive_portal (Arduino built-in)
|
DNSServer ; captive_portal (Arduino built-in)
|
||||||
crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir
|
|
||||||
droscy/esp_wireguard@0.4.2 ; wireguard
|
droscy/esp_wireguard@0.4.2 ; wireguard
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${common:arduino.build_flags}
|
${common:arduino.build_flags}
|
||||||
-Wno-nonnull-compare
|
-Wno-nonnull-compare
|
||||||
|
@ -123,8 +123,8 @@ lib_deps =
|
||||||
ESPmDNS ; mdns (Arduino built-in)
|
ESPmDNS ; mdns (Arduino built-in)
|
||||||
DNSServer ; captive_portal (Arduino built-in)
|
DNSServer ; captive_portal (Arduino built-in)
|
||||||
esphome/ESP32-audioI2S@2.0.7 ; i2s_audio
|
esphome/ESP32-audioI2S@2.0.7 ; i2s_audio
|
||||||
crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir
|
|
||||||
droscy/esp_wireguard@0.4.2 ; wireguard
|
droscy/esp_wireguard@0.4.2 ; wireguard
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${common:arduino.build_flags}
|
${common:arduino.build_flags}
|
||||||
-DUSE_ESP32
|
-DUSE_ESP32
|
||||||
|
|
|
@ -105,3 +105,33 @@ disable = [
|
||||||
|
|
||||||
[tool.pylint.FORMAT]
|
[tool.pylint.FORMAT]
|
||||||
expected-line-ending-format = "LF"
|
expected-line-ending-format = "LF"
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
required-version = ">=0.5.0"
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = [
|
||||||
|
"E", # pycodestyle
|
||||||
|
"F", # pyflakes/autoflake
|
||||||
|
"I", # isort
|
||||||
|
"PL", # pylint
|
||||||
|
"UP", # pyupgrade
|
||||||
|
]
|
||||||
|
|
||||||
|
ignore = [
|
||||||
|
"E501", # line too long
|
||||||
|
"PLR0911", # Too many return statements ({returns} > {max_returns})
|
||||||
|
"PLR0912", # Too many branches ({branches} > {max_branches})
|
||||||
|
"PLR0913", # Too many arguments to function call ({c_args} > {max_args})
|
||||||
|
"PLR0915", # Too many statements ({statements} > {max_statements})
|
||||||
|
"PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable
|
||||||
|
"PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.ruff.lint.isort]
|
||||||
|
force-sort-within-sections = true
|
||||||
|
known-first-party = [
|
||||||
|
"esphome",
|
||||||
|
]
|
||||||
|
combine-as-imports = true
|
||||||
|
split-on-trailing-comma = false
|
||||||
|
|
19
tests/components/heatpumpir/test.bk72xx-ard.yaml
Normal file
19
tests/components/heatpumpir/test.bk72xx-ard.yaml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
remote_transmitter:
|
||||||
|
pin: 6
|
||||||
|
carrier_duty_percent: 50%
|
||||||
|
|
||||||
|
climate:
|
||||||
|
- platform: heatpumpir
|
||||||
|
protocol: daikin
|
||||||
|
horizontal_default: mleft
|
||||||
|
vertical_default: mup
|
||||||
|
name: HeatpumpIR Climate
|
||||||
|
min_temperature: 18
|
||||||
|
max_temperature: 30
|
||||||
|
- platform: heatpumpir
|
||||||
|
protocol: panasonic_altdke
|
||||||
|
horizontal_default: mright
|
||||||
|
vertical_default: mdown
|
||||||
|
name: HeatpumpIR Climate
|
||||||
|
min_temperature: 18
|
||||||
|
max_temperature: 30
|
|
@ -2,4 +2,7 @@ wifi:
|
||||||
ssid: MySSID
|
ssid: MySSID
|
||||||
password: password1
|
password: password1
|
||||||
|
|
||||||
|
logger:
|
||||||
|
hardware_uart: UART0
|
||||||
|
|
||||||
improv_serial:
|
improv_serial:
|
8
tests/components/improv_serial/common-usb_cdc.yaml
Normal file
8
tests/components/improv_serial/common-usb_cdc.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
wifi:
|
||||||
|
ssid: MySSID
|
||||||
|
password: password1
|
||||||
|
|
||||||
|
logger:
|
||||||
|
hardware_uart: USB_CDC
|
||||||
|
|
||||||
|
improv_serial:
|
|
@ -0,0 +1,8 @@
|
||||||
|
wifi:
|
||||||
|
ssid: MySSID
|
||||||
|
password: password1
|
||||||
|
|
||||||
|
logger:
|
||||||
|
hardware_uart: USB_SERIAL_JTAG
|
||||||
|
|
||||||
|
improv_serial:
|
1
tests/components/improv_serial/test-uart0.esp32-ard.yaml
Normal file
1
tests/components/improv_serial/test-uart0.esp32-ard.yaml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-uart0.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-uart0.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-uart0.yaml
|
1
tests/components/improv_serial/test-uart0.esp32-idf.yaml
Normal file
1
tests/components/improv_serial/test-uart0.esp32-idf.yaml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-uart0.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-uart0.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-uart0.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-uart0.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-uart0.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-uart0.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-uart0.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-usb_cdc.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-usb_cdc.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-usb_cdc.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-usb_cdc.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-usb_cdc.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-usb_serial_jtag.yaml
|
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common-usb_serial_jtag.yaml
|
|
@ -1 +0,0 @@
|
||||||
<<: !include common.yaml
|
|
|
@ -1 +0,0 @@
|
||||||
<<: !include common.yaml
|
|
|
@ -1 +0,0 @@
|
||||||
<<: !include common.yaml
|
|
|
@ -1 +0,0 @@
|
||||||
<<: !include common.yaml
|
|
|
@ -1 +0,0 @@
|
||||||
<<: !include common.yaml
|
|
|
@ -1 +0,0 @@
|
||||||
<<: !include common.yaml
|
|
|
@ -18,3 +18,21 @@ sensor:
|
||||||
window_correction_factor: 1.0
|
window_correction_factor: 1.0
|
||||||
address: 0x53
|
address: 0x53
|
||||||
update_interval: 60s
|
update_interval: 60s
|
||||||
|
- platform: ltr390
|
||||||
|
uv:
|
||||||
|
name: LTR390 UV
|
||||||
|
uv_index:
|
||||||
|
name: LTR390 UVI
|
||||||
|
light:
|
||||||
|
name: LTR390 Light
|
||||||
|
ambient_light:
|
||||||
|
name: LTR390 ALS
|
||||||
|
gain:
|
||||||
|
ambient_light: X9
|
||||||
|
uv: X3
|
||||||
|
resolution:
|
||||||
|
ambient_light: 18
|
||||||
|
uv: 13
|
||||||
|
window_correction_factor: 1.0
|
||||||
|
address: 0x53
|
||||||
|
update_interval: 60s
|
||||||
|
|
|
@ -13,7 +13,9 @@ sensor:
|
||||||
name: LTR390 Light
|
name: LTR390 Light
|
||||||
ambient_light:
|
ambient_light:
|
||||||
name: LTR390 ALS
|
name: LTR390 ALS
|
||||||
gain: X3
|
gain:
|
||||||
|
ambient_light: X9
|
||||||
|
uv: X3
|
||||||
resolution: 18
|
resolution: 18
|
||||||
window_correction_factor: 1.0
|
window_correction_factor: 1.0
|
||||||
address: 0x53
|
address: 0x53
|
||||||
|
|
|
@ -2,6 +2,37 @@ wifi:
|
||||||
ssid: MySSID
|
ssid: MySSID
|
||||||
password: password1
|
password: password1
|
||||||
|
|
||||||
web_server:
|
binary_sensor:
|
||||||
port: 8080
|
cover:
|
||||||
version: 2
|
fan:
|
||||||
|
light:
|
||||||
|
sensor:
|
||||||
|
switch:
|
||||||
|
button:
|
||||||
|
text_sensor:
|
||||||
|
climate:
|
||||||
|
number:
|
||||||
|
text:
|
||||||
|
select:
|
||||||
|
lock:
|
||||||
|
valve:
|
||||||
|
alarm_control_panel:
|
||||||
|
api:
|
||||||
|
time:
|
||||||
|
- platform: homeassistant
|
||||||
|
id: homeassistant_time
|
||||||
|
datetime:
|
||||||
|
- platform: template
|
||||||
|
id: my_datetime_date
|
||||||
|
type: date
|
||||||
|
optimistic: yes
|
||||||
|
- platform: template
|
||||||
|
id: my_datetime_time
|
||||||
|
type: time
|
||||||
|
optimistic: yes
|
||||||
|
- platform: template
|
||||||
|
id: my_datetime
|
||||||
|
type: datetime
|
||||||
|
optimistic: yes
|
||||||
|
event:
|
||||||
|
update:
|
||||||
|
|
5
tests/components/web_server/common_v1.yaml
Normal file
5
tests/components/web_server/common_v1.yaml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<<: !include common.yaml
|
||||||
|
|
||||||
|
web_server:
|
||||||
|
port: 8080
|
||||||
|
version: 1
|
5
tests/components/web_server/common_v2.yaml
Normal file
5
tests/components/web_server/common_v2.yaml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<<: !include common.yaml
|
||||||
|
|
||||||
|
web_server:
|
||||||
|
port: 8080
|
||||||
|
version: 2
|
|
@ -1 +1 @@
|
||||||
<<: !include common.yaml
|
<<: !include common_v2.yaml
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<<: !include common.yaml
|
<<: !include common_v2.yaml
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<<: !include common.yaml
|
<<: !include common_v2.yaml
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<<: !include common.yaml
|
<<: !include common_v2.yaml
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<<: !include common.yaml
|
<<: !include common_v2.yaml
|
||||||
|
|
1
tests/components/web_server/test_v1.esp32-ard.yaml
Normal file
1
tests/components/web_server/test_v1.esp32-ard.yaml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<<: !include common_v1.yaml
|
Loading…
Reference in a new issue