Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f27757039 | ||
|
|
532907219b | ||
|
|
eeaba74553 | ||
|
|
dd637582a4 | ||
|
|
b0d12aeea1 | ||
|
|
bdbd813455 | ||
|
|
a6fac2b175 | ||
|
|
5ce923ea90 | ||
|
|
29f0508dc2 | ||
|
|
3ffa59f0cd | ||
|
|
790d6ef94c | ||
|
|
7828f48b9a | ||
|
|
9fbb3659a6 | ||
|
|
fee446c28a | ||
|
|
1d56f0b035 | ||
|
|
341fddb9aa | ||
|
|
456824669f | ||
|
|
62f3039d82 | ||
|
|
be4c718859 | ||
|
|
c2f9ed7c59 | ||
|
|
bfac6607d1 |
@@ -312,8 +312,12 @@ void Climate::add_on_state_callback(std::function<void()> &&callback) {
|
||||
this->state_callback_.add(std::move(callback));
|
||||
}
|
||||
|
||||
// Random 32bit value; If this changes existing restore preferences are invalidated
|
||||
static const uint32_t RESTORE_STATE_VERSION = 0x848EA6ADUL;
|
||||
|
||||
optional<ClimateDeviceRestoreState> Climate::restore_state_() {
|
||||
this->rtc_ = global_preferences.make_preference<ClimateDeviceRestoreState>(this->get_object_id_hash());
|
||||
this->rtc_ =
|
||||
global_preferences.make_preference<ClimateDeviceRestoreState>(this->get_object_id_hash() ^ RESTORE_STATE_VERSION);
|
||||
ClimateDeviceRestoreState recovered{};
|
||||
if (!this->rtc_.load(&recovered))
|
||||
return {};
|
||||
|
||||
@@ -120,6 +120,7 @@ class ClimateCall {
|
||||
};
|
||||
|
||||
/// Struct used to save the state of the climate device in restore memory.
|
||||
/// Make sure to update RESTORE_STATE_VERSION when changing the struct entries.
|
||||
struct ClimateDeviceRestoreState {
|
||||
ClimateMode mode;
|
||||
bool uses_custom_fan_mode{false};
|
||||
|
||||
@@ -31,7 +31,9 @@ DisplayPageShowPrevAction = display_ns.class_(
|
||||
DisplayIsDisplayingPageCondition = display_ns.class_(
|
||||
"DisplayIsDisplayingPageCondition", automation.Condition
|
||||
)
|
||||
DisplayOnPageChangeTrigger = display_ns.class_("DisplayOnPageChangeTrigger")
|
||||
DisplayOnPageChangeTrigger = display_ns.class_(
|
||||
"DisplayOnPageChangeTrigger", automation.Trigger
|
||||
)
|
||||
|
||||
CONF_ON_PAGE_CHANGE = "on_page_change"
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ void DutyCycleSensor::setup() {
|
||||
this->store_.pin = this->pin_->to_isr();
|
||||
this->store_.last_level = this->pin_->digital_read();
|
||||
this->last_update_ = micros();
|
||||
this->store_.last_interrupt = micros();
|
||||
|
||||
this->pin_->attach_interrupt(DutyCycleSensorStore::gpio_intr, &this->store_, CHANGE);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ class DutyCycleSensor : public sensor::Sensor, public PollingComponent {
|
||||
protected:
|
||||
GPIOPin *pin_;
|
||||
|
||||
DutyCycleSensorStore store_;
|
||||
DutyCycleSensorStore store_{};
|
||||
uint32_t last_update_;
|
||||
};
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ def _process_git_config(config: dict, refresh) -> str:
|
||||
age = datetime.datetime.now() - datetime.datetime.fromtimestamp(
|
||||
file_timestamp.stat().st_mtime
|
||||
)
|
||||
if age.seconds > refresh.total_seconds:
|
||||
if age.total_seconds() > refresh.total_seconds:
|
||||
_LOGGER.info("Updating %s", key)
|
||||
_LOGGER.debug("Location: %s", repo_dir)
|
||||
# Stash local changes (if any)
|
||||
|
||||
@@ -45,6 +45,7 @@ void HLW8012Component::dump_config() {
|
||||
LOG_SENSOR(" ", "Voltage", this->voltage_sensor_)
|
||||
LOG_SENSOR(" ", "Current", this->current_sensor_)
|
||||
LOG_SENSOR(" ", "Power", this->power_sensor_)
|
||||
LOG_SENSOR(" ", "Energy", this->energy_sensor_)
|
||||
}
|
||||
float HLW8012Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||
void HLW8012Component::update() {
|
||||
|
||||
@@ -39,8 +39,8 @@ void MQTTNumberComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryCo
|
||||
// https://www.home-assistant.io/integrations/number.mqtt/
|
||||
if (!traits.get_icon().empty())
|
||||
root["icon"] = traits.get_icon();
|
||||
root["min_value"] = traits.get_min_value();
|
||||
root["max_value"] = traits.get_max_value();
|
||||
root["min"] = traits.get_min_value();
|
||||
root["max"] = traits.get_max_value();
|
||||
root["step"] = traits.get_step();
|
||||
|
||||
config.command_topic = true;
|
||||
|
||||
@@ -37,7 +37,7 @@ void PIDClimate::control(const climate::ClimateCall &call) {
|
||||
|
||||
// If switching to off mode, set output immediately
|
||||
if (this->mode == climate::CLIMATE_MODE_OFF)
|
||||
this->handle_non_auto_mode_();
|
||||
this->write_output_(0.0f);
|
||||
|
||||
this->publish_state();
|
||||
}
|
||||
@@ -98,15 +98,6 @@ void PIDClimate::write_output_(float value) {
|
||||
}
|
||||
this->pid_computed_callback_.call();
|
||||
}
|
||||
void PIDClimate::handle_non_auto_mode_() {
|
||||
// in non-auto mode, switch directly to appropriate action
|
||||
// - OFF mode -> Output at 0%
|
||||
if (this->mode == climate::CLIMATE_MODE_OFF) {
|
||||
this->write_output_(0.0);
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
void PIDClimate::update_pid_() {
|
||||
float value;
|
||||
if (isnan(this->current_temperature) || isnan(this->target_temperature)) {
|
||||
@@ -135,7 +126,7 @@ void PIDClimate::update_pid_() {
|
||||
}
|
||||
|
||||
if (this->mode == climate::CLIMATE_MODE_OFF) {
|
||||
this->handle_non_auto_mode_();
|
||||
this->write_output_(0.0);
|
||||
} else {
|
||||
this->write_output_(value);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ class PIDClimate : public climate::Climate, public Component {
|
||||
bool supports_heat_() const { return this->heat_output_ != nullptr; }
|
||||
|
||||
void write_output_(float value);
|
||||
void handle_non_auto_mode_();
|
||||
|
||||
/// The sensor used for getting the current temperature
|
||||
sensor::Sensor *sensor_;
|
||||
|
||||
@@ -11,8 +11,8 @@ from esphome.const import (
|
||||
CONF_TOTAL,
|
||||
CONF_VALUE,
|
||||
ICON_PULSE,
|
||||
LAST_RESET_TYPE_AUTO,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
STATE_CLASS_NONE,
|
||||
UNIT_PULSES,
|
||||
UNIT_PULSES_PER_MINUTE,
|
||||
DEVICE_CLASS_EMPTY,
|
||||
@@ -59,7 +59,12 @@ CONFIG_SCHEMA = sensor.sensor_schema(
|
||||
cv.Optional(CONF_INTERNAL_FILTER, default="13us"): validate_internal_filter,
|
||||
cv.Optional(CONF_TIMEOUT, default="5min"): validate_timeout,
|
||||
cv.Optional(CONF_TOTAL): sensor.sensor_schema(
|
||||
UNIT_PULSES, ICON_PULSE, 0, DEVICE_CLASS_EMPTY, STATE_CLASS_NONE
|
||||
UNIT_PULSES,
|
||||
ICON_PULSE,
|
||||
0,
|
||||
DEVICE_CLASS_EMPTY,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
LAST_RESET_TYPE_AUTO,
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -41,6 +41,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase,
|
||||
bool initialized_{false};
|
||||
std::vector<rmt_item32_t> rmt_temp_;
|
||||
esp_err_t error_code_{ESP_OK};
|
||||
bool inverted_{false};
|
||||
#endif
|
||||
uint8_t carrier_duty_percent_{50};
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace remote_transmitter {
|
||||
|
||||
static const char *const TAG = "remote_transmitter";
|
||||
|
||||
void RemoteTransmitterComponent::setup() {}
|
||||
void RemoteTransmitterComponent::setup() { this->configure_rmt(); }
|
||||
|
||||
void RemoteTransmitterComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "Remote Transmitter...");
|
||||
@@ -50,6 +50,7 @@ void RemoteTransmitterComponent::configure_rmt() {
|
||||
} else {
|
||||
c.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
|
||||
c.tx_config.idle_level = RMT_IDLE_LEVEL_HIGH;
|
||||
this->inverted_ = true;
|
||||
}
|
||||
|
||||
esp_err_t error = rmt_config(&c);
|
||||
@@ -95,10 +96,10 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
||||
val -= item;
|
||||
|
||||
if (rmt_i % 2 == 0) {
|
||||
rmt_item.level0 = static_cast<uint32_t>(level);
|
||||
rmt_item.level0 = static_cast<uint32_t>(level ^ this->inverted_);
|
||||
rmt_item.duration0 = static_cast<uint32_t>(item);
|
||||
} else {
|
||||
rmt_item.level1 = static_cast<uint32_t>(level);
|
||||
rmt_item.level1 = static_cast<uint32_t>(level ^ this->inverted_);
|
||||
rmt_item.duration1 = static_cast<uint32_t>(item);
|
||||
this->rmt_temp_.push_back(rmt_item);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,10 @@ void CronTrigger::loop() {
|
||||
return;
|
||||
|
||||
if (this->last_check_.has_value()) {
|
||||
if (*this->last_check_ >= time) {
|
||||
if (*this->last_check_ > time && this->last_check_->timestamp - time.timestamp > 900) {
|
||||
// We went back in time (a lot), probably caused by time synchronization
|
||||
ESP_LOGW(TAG, "Time has jumped back!");
|
||||
} else if (*this->last_check_ >= time) {
|
||||
// already handled this one
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor, time
|
||||
from esphome.const import CONF_ID, CONF_TIME_ID
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_TIME_ID,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
ICON_EMPTY,
|
||||
LAST_RESET_TYPE_AUTO,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_EMPTY,
|
||||
)
|
||||
|
||||
DEPENDENCIES = ["time"]
|
||||
|
||||
@@ -11,13 +19,24 @@ TotalDailyEnergy = total_daily_energy_ns.class_(
|
||||
"TotalDailyEnergy", sensor.Sensor, cg.Component
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(TotalDailyEnergy),
|
||||
cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock),
|
||||
cv.Required(CONF_POWER_ID): cv.use_id(sensor.Sensor),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
CONFIG_SCHEMA = (
|
||||
sensor.sensor_schema(
|
||||
UNIT_EMPTY,
|
||||
ICON_EMPTY,
|
||||
0,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
LAST_RESET_TYPE_AUTO,
|
||||
)
|
||||
.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(TotalDailyEnergy),
|
||||
cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock),
|
||||
cv.Required(CONF_POWER_ID): cv.use_id(sensor.Sensor),
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace esphome {
|
||||
namespace tuya {
|
||||
|
||||
static const char *const TAG = "tuya";
|
||||
static const int COMMAND_DELAY = 50;
|
||||
static const int COMMAND_DELAY = 10;
|
||||
static const int RECEIVE_TIMEOUT = 300;
|
||||
|
||||
void Tuya::setup() {
|
||||
@@ -114,6 +114,8 @@ void Tuya::handle_char_(uint8_t c) {
|
||||
this->rx_message_.push_back(c);
|
||||
if (!this->validate_message_()) {
|
||||
this->rx_message_.clear();
|
||||
} else {
|
||||
this->last_rx_char_timestamp_ = millis();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,7 +359,12 @@ void Tuya::send_raw_command_(TuyaCommand command) {
|
||||
}
|
||||
|
||||
void Tuya::process_command_queue_() {
|
||||
uint32_t delay = millis() - this->last_command_timestamp_;
|
||||
uint32_t now = millis();
|
||||
uint32_t delay = now - this->last_command_timestamp_;
|
||||
|
||||
if (now - this->last_rx_char_timestamp_ > RECEIVE_TIMEOUT) {
|
||||
this->rx_message_.clear();
|
||||
}
|
||||
|
||||
if (this->expected_response_.has_value() && delay > RECEIVE_TIMEOUT) {
|
||||
this->expected_response_.reset();
|
||||
|
||||
@@ -107,6 +107,7 @@ class Tuya : public Component, public uart::UARTDevice {
|
||||
int gpio_status_ = -1;
|
||||
int gpio_reset_ = -1;
|
||||
uint32_t last_command_timestamp_ = 0;
|
||||
uint32_t last_rx_char_timestamp_ = 0;
|
||||
std::string product_ = "";
|
||||
std::vector<TuyaDatapointListener> listeners_;
|
||||
std::vector<TuyaDatapoint> datapoints_;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Constants used by esphome."""
|
||||
|
||||
__version__ = "1.20.1"
|
||||
__version__ = "1.20.4"
|
||||
|
||||
ESP_PLATFORM_ESP32 = "ESP32"
|
||||
ESP_PLATFORM_ESP8266 = "ESP8266"
|
||||
|
||||
@@ -1104,7 +1104,7 @@ def shorthand_input_pullup_pin(value):
|
||||
|
||||
def shorthand_analog_pin(value):
|
||||
value = analog_pin(value)
|
||||
return GPIO_FULL_INPUT_PIN_SCHEMA({CONF_NUMBER: value})
|
||||
return GPIO_FULL_ANALOG_PIN_SCHEMA({CONF_NUMBER: value})
|
||||
|
||||
|
||||
def validate_has_interrupt(value):
|
||||
|
||||
@@ -11,4 +11,4 @@ ifaddr==0.1.7
|
||||
platformio==5.1.1
|
||||
esptool==2.8
|
||||
click==7.1.2
|
||||
esphome-dashboard==20210719.0
|
||||
esphome-dashboard==20210728.0
|
||||
|
||||
Reference in New Issue
Block a user