Merge pull request #2723 from esphome/bump-2021.11.0b4

2021.11.0b4
This commit is contained in:
Jesse Hills 2021-11-15 11:42:59 +13:00 committed by GitHub
commit f2aea02210
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 162 additions and 89 deletions

View file

@ -1,6 +1,7 @@
#ifdef USE_ESP32 #ifdef USE_ESP32
#include "esp32_touch.h" #include "esp32_touch.h"
#include "esphome/core/application.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "esphome/core/hal.h" #include "esphome/core/hal.h"
@ -125,6 +126,8 @@ void ESP32TouchComponent::loop() {
if (should_print) { if (should_print) {
ESP_LOGD(TAG, "Touch Pad '%s' (T%u): %u", child->get_name().c_str(), child->get_touch_pad(), value); ESP_LOGD(TAG, "Touch Pad '%s' (T%u): %u", child->get_name().c_str(), child->get_touch_pad(), value);
} }
App.feed_wdt();
} }
if (should_print) { if (should_print) {

View file

@ -1,10 +1,11 @@
#ifdef USE_ARDUINO #ifdef USE_ARDUINO
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "adapter.h" #include "ac_adapter.h"
namespace esphome { namespace esphome {
namespace midea { namespace midea {
namespace ac {
const char *const Constants::TAG = "midea"; const char *const Constants::TAG = "midea";
const std::string Constants::FREEZE_PROTECTION = "freeze protection"; const std::string Constants::FREEZE_PROTECTION = "freeze protection";
@ -171,6 +172,7 @@ void Converters::to_climate_traits(ClimateTraits &traits, const dudanov::midea::
traits.add_supported_custom_preset(Constants::FREEZE_PROTECTION); traits.add_supported_custom_preset(Constants::FREEZE_PROTECTION);
} }
} // namespace ac
} // namespace midea } // namespace midea
} // namespace esphome } // namespace esphome

View file

@ -2,12 +2,15 @@
#ifdef USE_ARDUINO #ifdef USE_ARDUINO
// MideaUART
#include <Appliance/AirConditioner/AirConditioner.h> #include <Appliance/AirConditioner/AirConditioner.h>
#include "esphome/components/climate/climate_traits.h" #include "esphome/components/climate/climate_traits.h"
#include "appliance_base.h" #include "air_conditioner.h"
namespace esphome { namespace esphome {
namespace midea { namespace midea {
namespace ac {
using MideaMode = dudanov::midea::ac::Mode; using MideaMode = dudanov::midea::ac::Mode;
using MideaSwingMode = dudanov::midea::ac::SwingMode; using MideaSwingMode = dudanov::midea::ac::SwingMode;
@ -41,6 +44,7 @@ class Converters {
static void to_climate_traits(ClimateTraits &traits, const dudanov::midea::ac::Capabilities &capabilities); static void to_climate_traits(ClimateTraits &traits, const dudanov::midea::ac::Capabilities &capabilities);
}; };
} // namespace ac
} // namespace midea } // namespace midea
} // namespace esphome } // namespace esphome

View file

@ -7,6 +7,7 @@
namespace esphome { namespace esphome {
namespace midea { namespace midea {
namespace ac {
template<typename... Ts> class MideaActionBase : public Action<Ts...> { template<typename... Ts> class MideaActionBase : public Action<Ts...> {
public: public:
@ -55,6 +56,7 @@ template<typename... Ts> class PowerOffAction : public MideaActionBase<Ts...> {
void play(Ts... x) override { this->parent_->do_power_off(); } void play(Ts... x) override { this->parent_->do_power_off(); }
}; };
} // namespace ac
} // namespace midea } // namespace midea
} // namespace esphome } // namespace esphome

View file

@ -2,13 +2,11 @@
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "air_conditioner.h" #include "air_conditioner.h"
#include "adapter.h" #include "ac_adapter.h"
#ifdef USE_REMOTE_TRANSMITTER
#include "midea_ir.h"
#endif
namespace esphome { namespace esphome {
namespace midea { namespace midea {
namespace ac {
static void set_sensor(Sensor *sensor, float value) { static void set_sensor(Sensor *sensor, float value) {
if (sensor != nullptr && (!sensor->has_state() || sensor->get_raw_state() != value)) if (sensor != nullptr && (!sensor->has_state() || sensor->get_raw_state() != value))
@ -122,7 +120,7 @@ void AirConditioner::dump_config() {
void AirConditioner::do_follow_me(float temperature, bool beeper) { void AirConditioner::do_follow_me(float temperature, bool beeper) {
#ifdef USE_REMOTE_TRANSMITTER #ifdef USE_REMOTE_TRANSMITTER
IrFollowMeData data(static_cast<uint8_t>(lroundf(temperature)), beeper); IrFollowMeData data(static_cast<uint8_t>(lroundf(temperature)), beeper);
this->transmit_ir(data); this->transmitter_.transmit(data);
#else #else
ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component"); ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component");
#endif #endif
@ -131,7 +129,7 @@ void AirConditioner::do_follow_me(float temperature, bool beeper) {
void AirConditioner::do_swing_step() { void AirConditioner::do_swing_step() {
#ifdef USE_REMOTE_TRANSMITTER #ifdef USE_REMOTE_TRANSMITTER
IrSpecialData data(0x01); IrSpecialData data(0x01);
this->transmit_ir(data); this->transmitter_.transmit(data);
#else #else
ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component"); ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component");
#endif #endif
@ -143,13 +141,14 @@ void AirConditioner::do_display_toggle() {
} else { } else {
#ifdef USE_REMOTE_TRANSMITTER #ifdef USE_REMOTE_TRANSMITTER
IrSpecialData data(0x08); IrSpecialData data(0x08);
this->transmit_ir(data); this->transmitter_.transmit(data);
#else #else
ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component"); ESP_LOGW(Constants::TAG, "Action needs remote_transmitter component");
#endif #endif
} }
} }
} // namespace ac
} // namespace midea } // namespace midea
} // namespace esphome } // namespace esphome

View file

@ -2,17 +2,25 @@
#ifdef USE_ARDUINO #ifdef USE_ARDUINO
// MideaUART
#include <Appliance/AirConditioner/AirConditioner.h> #include <Appliance/AirConditioner/AirConditioner.h>
#include "appliance_base.h" #include "appliance_base.h"
#include "esphome/components/sensor/sensor.h" #include "esphome/components/sensor/sensor.h"
namespace esphome { namespace esphome {
namespace midea { namespace midea {
namespace ac {
using sensor::Sensor; using sensor::Sensor;
using climate::ClimateCall; using climate::ClimateCall;
using climate::ClimatePreset;
using climate::ClimateTraits;
using climate::ClimateMode;
using climate::ClimateSwingMode;
using climate::ClimateFanMode;
class AirConditioner : public ApplianceBase<dudanov::midea::ac::AirConditioner> { class AirConditioner : public ApplianceBase<dudanov::midea::ac::AirConditioner>, public climate::Climate {
public: public:
void dump_config() override; void dump_config() override;
void set_outdoor_temperature_sensor(Sensor *sensor) { this->outdoor_sensor_ = sensor; } void set_outdoor_temperature_sensor(Sensor *sensor) { this->outdoor_sensor_ = sensor; }
@ -31,15 +39,26 @@ class AirConditioner : public ApplianceBase<dudanov::midea::ac::AirConditioner>
void do_beeper_off() { this->set_beeper_feedback(false); } void do_beeper_off() { this->set_beeper_feedback(false); }
void do_power_on() { this->base_.setPowerState(true); } void do_power_on() { this->base_.setPowerState(true); }
void do_power_off() { this->base_.setPowerState(false); } void do_power_off() { this->base_.setPowerState(false); }
void set_supported_modes(const std::set<ClimateMode> &modes) { this->supported_modes_ = modes; }
void set_supported_swing_modes(const std::set<ClimateSwingMode> &modes) { this->supported_swing_modes_ = modes; }
void set_supported_presets(const std::set<ClimatePreset> &presets) { this->supported_presets_ = presets; }
void set_custom_presets(const std::set<std::string> &presets) { this->supported_custom_presets_ = presets; }
void set_custom_fan_modes(const std::set<std::string> &modes) { this->supported_custom_fan_modes_ = modes; }
protected: protected:
void control(const ClimateCall &call) override; void control(const ClimateCall &call) override;
ClimateTraits traits() override; ClimateTraits traits() override;
std::set<ClimateMode> supported_modes_{};
std::set<ClimateSwingMode> supported_swing_modes_{};
std::set<ClimatePreset> supported_presets_{};
std::set<std::string> supported_custom_presets_{};
std::set<std::string> supported_custom_fan_modes_{};
Sensor *outdoor_sensor_{nullptr}; Sensor *outdoor_sensor_{nullptr};
Sensor *humidity_sensor_{nullptr}; Sensor *humidity_sensor_{nullptr};
Sensor *power_sensor_{nullptr}; Sensor *power_sensor_{nullptr};
}; };
} // namespace ac
} // namespace midea } // namespace midea
} // namespace esphome } // namespace esphome

View file

@ -2,84 +2,97 @@
#ifdef USE_ARDUINO #ifdef USE_ARDUINO
// MideaUART
#include <Appliance/ApplianceBase.h>
#include <Helpers/Logger.h>
// Include global defines
#include "esphome/core/defines.h"
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include "esphome/components/uart/uart.h" #include "esphome/components/uart/uart.h"
#include "esphome/components/climate/climate.h" #include "esphome/components/climate/climate.h"
#ifdef USE_REMOTE_TRANSMITTER #include "ir_transmitter.h"
#include "esphome/components/remote_base/midea_protocol.h"
#include "esphome/components/remote_transmitter/remote_transmitter.h"
#endif
#include <Appliance/ApplianceBase.h>
#include <Helpers/Logger.h>
namespace esphome { namespace esphome {
namespace midea { namespace midea {
using climate::ClimatePreset; /* Stream from UART component */
using climate::ClimateTraits; class UARTStream : public Stream {
using climate::ClimateMode; public:
using climate::ClimateSwingMode; void set_uart(uart::UARTComponent *uart) { this->uart_ = uart; }
using climate::ClimateFanMode;
template<typename T> /* Stream interface implementation */
class ApplianceBase : public Component, public uart::UARTDevice, public climate::Climate, public Stream {
int available() override { return this->uart_->available(); }
int read() override {
uint8_t data;
this->uart_->read_byte(&data);
return data;
}
int peek() override {
uint8_t data;
this->uart_->peek_byte(&data);
return data;
}
size_t write(uint8_t data) override {
this->uart_->write_byte(data);
return 1;
}
size_t write(const uint8_t *data, size_t size) override {
this->uart_->write_array(data, size);
return size;
}
void flush() override { this->uart_->flush(); }
protected:
uart::UARTComponent *uart_;
};
template<typename T> class ApplianceBase : public Component {
static_assert(std::is_base_of<dudanov::midea::ApplianceBase, T>::value, static_assert(std::is_base_of<dudanov::midea::ApplianceBase, T>::value,
"T must derive from dudanov::midea::ApplianceBase class"); "T must derive from dudanov::midea::ApplianceBase class");
public: public:
ApplianceBase() { ApplianceBase() {
this->base_.setStream(this); this->base_.setStream(&this->stream_);
this->base_.addOnStateCallback(std::bind(&ApplianceBase::on_status_change, this)); this->base_.addOnStateCallback(std::bind(&ApplianceBase::on_status_change, this));
dudanov::midea::ApplianceBase::setLogger( dudanov::midea::ApplianceBase::setLogger(
[](int level, const char *tag, int line, const String &format, va_list args) { [](int level, const char *tag, int line, const String &format, va_list args) {
esp_log_vprintf_(level, tag, line, format.c_str(), args); esp_log_vprintf_(level, tag, line, format.c_str(), args);
}); });
} }
bool can_proceed() override {
return this->base_.getAutoconfStatus() != dudanov::midea::AutoconfStatus::AUTOCONF_PROGRESS; #ifdef USE_REMOTE_TRANSMITTER
} void set_transmitter(RemoteTransmitterBase *transmitter) { this->transmitter_.set_transmitter(transmitter); }
float get_setup_priority() const override { return setup_priority::BEFORE_CONNECTION; } #endif
void setup() override { this->base_.setup(); }
void loop() override { this->base_.loop(); } /* UART communication */
void set_uart_parent(uart::UARTComponent *parent) { this->stream_.set_uart(parent); }
void set_period(uint32_t ms) { this->base_.setPeriod(ms); } void set_period(uint32_t ms) { this->base_.setPeriod(ms); }
void set_response_timeout(uint32_t ms) { this->base_.setTimeout(ms); } void set_response_timeout(uint32_t ms) { this->base_.setTimeout(ms); }
void set_request_attempts(uint32_t attempts) { this->base_.setNumAttempts(attempts); } void set_request_attempts(uint32_t attempts) { this->base_.setNumAttempts(attempts); }
/* Component methods */
void setup() override { this->base_.setup(); }
void loop() override { this->base_.loop(); }
float get_setup_priority() const override { return setup_priority::BEFORE_CONNECTION; }
bool can_proceed() override {
return this->base_.getAutoconfStatus() != dudanov::midea::AutoconfStatus::AUTOCONF_PROGRESS;
}
void set_beeper_feedback(bool state) { this->base_.setBeeper(state); } void set_beeper_feedback(bool state) { this->base_.setBeeper(state); }
void set_autoconf(bool value) { this->base_.setAutoconf(value); } void set_autoconf(bool value) { this->base_.setAutoconf(value); }
void set_supported_modes(const std::set<ClimateMode> &modes) { this->supported_modes_ = modes; }
void set_supported_swing_modes(const std::set<ClimateSwingMode> &modes) { this->supported_swing_modes_ = modes; }
void set_supported_presets(const std::set<ClimatePreset> &presets) { this->supported_presets_ = presets; }
void set_custom_presets(const std::set<std::string> &presets) { this->supported_custom_presets_ = presets; }
void set_custom_fan_modes(const std::set<std::string> &modes) { this->supported_custom_fan_modes_ = modes; }
virtual void on_status_change() = 0; virtual void on_status_change() = 0;
#ifdef USE_REMOTE_TRANSMITTER
void set_transmitter(remote_transmitter::RemoteTransmitterComponent *transmitter) {
this->transmitter_ = transmitter;
}
void transmit_ir(remote_base::MideaData &data) {
data.finalize();
auto transmit = this->transmitter_->transmit();
remote_base::MideaProtocol().encode(transmit.get_data(), data);
transmit.perform();
}
#endif
int available() override { return uart::UARTDevice::available(); }
int read() override { return uart::UARTDevice::read(); }
int peek() override { return uart::UARTDevice::peek(); }
void flush() override { uart::UARTDevice::flush(); }
size_t write(uint8_t data) override { return uart::UARTDevice::write(data); }
protected: protected:
T base_; T base_;
std::set<ClimateMode> supported_modes_{}; UARTStream stream_;
std::set<ClimateSwingMode> supported_swing_modes_{};
std::set<ClimatePreset> supported_presets_{};
std::set<std::string> supported_custom_presets_{};
std::set<std::string> supported_custom_fan_modes_{};
#ifdef USE_REMOTE_TRANSMITTER #ifdef USE_REMOTE_TRANSMITTER
remote_transmitter::RemoteTransmitterComponent *transmitter_{nullptr}; IrTransmitter transmitter_;
#endif #endif
}; };

View file

@ -40,9 +40,9 @@ AUTO_LOAD = ["sensor"]
CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature" CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature"
CONF_POWER_USAGE = "power_usage" CONF_POWER_USAGE = "power_usage"
CONF_HUMIDITY_SETPOINT = "humidity_setpoint" CONF_HUMIDITY_SETPOINT = "humidity_setpoint"
midea_ns = cg.esphome_ns.namespace("midea") midea_ac_ns = cg.esphome_ns.namespace("midea").namespace("ac")
AirConditioner = midea_ns.class_("AirConditioner", climate.Climate, cg.Component) AirConditioner = midea_ac_ns.class_("AirConditioner", climate.Climate, cg.Component)
Capabilities = midea_ns.namespace("Constants") Capabilities = midea_ac_ns.namespace("Constants")
def templatize(value): def templatize(value):
@ -156,13 +156,13 @@ CONFIG_SCHEMA = cv.All(
) )
# Actions # Actions
FollowMeAction = midea_ns.class_("FollowMeAction", automation.Action) FollowMeAction = midea_ac_ns.class_("FollowMeAction", automation.Action)
DisplayToggleAction = midea_ns.class_("DisplayToggleAction", automation.Action) DisplayToggleAction = midea_ac_ns.class_("DisplayToggleAction", automation.Action)
SwingStepAction = midea_ns.class_("SwingStepAction", automation.Action) SwingStepAction = midea_ac_ns.class_("SwingStepAction", automation.Action)
BeeperOnAction = midea_ns.class_("BeeperOnAction", automation.Action) BeeperOnAction = midea_ac_ns.class_("BeeperOnAction", automation.Action)
BeeperOffAction = midea_ns.class_("BeeperOffAction", automation.Action) BeeperOffAction = midea_ac_ns.class_("BeeperOffAction", automation.Action)
PowerOnAction = midea_ns.class_("PowerOnAction", automation.Action) PowerOnAction = midea_ac_ns.class_("PowerOnAction", automation.Action)
PowerOffAction = midea_ns.class_("PowerOffAction", automation.Action) PowerOffAction = midea_ac_ns.class_("PowerOffAction", automation.Action)
MIDEA_ACTION_BASE_SCHEMA = cv.Schema( MIDEA_ACTION_BASE_SCHEMA = cv.Schema(
{ {

View file

@ -7,6 +7,7 @@
namespace esphome { namespace esphome {
namespace midea { namespace midea {
using remote_base::RemoteTransmitterBase;
using IrData = remote_base::MideaData; using IrData = remote_base::MideaData;
class IrFollowMeData : public IrData { class IrFollowMeData : public IrData {
@ -38,6 +39,20 @@ class IrSpecialData : public IrData {
IrSpecialData(uint8_t code) : IrData({MIDEA_TYPE_SPECIAL, code, 0xFF, 0xFF, 0xFF}) {} IrSpecialData(uint8_t code) : IrData({MIDEA_TYPE_SPECIAL, code, 0xFF, 0xFF, 0xFF}) {}
}; };
class IrTransmitter {
public:
void set_transmitter(RemoteTransmitterBase *transmitter) { this->transmitter_ = transmitter; }
void transmit(IrData &data) {
data.finalize();
auto transmit = this->transmitter_->transmit();
remote_base::MideaProtocol().encode(transmit.get_data(), data);
transmit.perform();
}
protected:
RemoteTransmitterBase *transmitter_{nullptr};
};
} // namespace midea } // namespace midea
} // namespace esphome } // namespace esphome

View file

@ -129,14 +129,14 @@ async def to_code(config):
return_type=cg.optional.template(float), return_type=cg.optional.template(float),
) )
cg.add(var.set_template(template_)) cg.add(var.set_template(template_))
if CONF_WRITE_LAMBDA in config: if CONF_WRITE_LAMBDA in config:
template_ = await cg.process_lambda( template_ = await cg.process_lambda(
config[CONF_WRITE_LAMBDA], config[CONF_WRITE_LAMBDA],
[ [
(ModbusNumber.operator("ptr"), "item"), (ModbusNumber.operator("ptr"), "item"),
(cg.float_, "x"), (cg.float_, "x"),
(cg.std_vector.template(cg.uint16).operator("ref"), "payload"), (cg.std_vector.template(cg.uint16).operator("ref"), "payload"),
], ],
return_type=cg.optional.template(float), return_type=cg.optional.template(float),
) )
cg.add(var.set_write_template(template_)) cg.add(var.set_write_template(template_))

View file

@ -41,7 +41,7 @@ NumberInRangeCondition = number_ns.class_(
icon = cv.icon icon = cv.icon
NUMBER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend( NUMBER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend(
{ {
cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTNumberComponent), cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTNumberComponent),
cv.GenerateID(): cv.declare_id(Number), cv.GenerateID(): cv.declare_id(Number),

View file

@ -30,7 +30,7 @@ SelectSetAction = select_ns.class_("SelectSetAction", automation.Action)
icon = cv.icon icon = cv.icon
SELECT_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend( SELECT_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend(
{ {
cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTSelectComponent), cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTSelectComponent),
cv.GenerateID(): cv.declare_id(Select), cv.GenerateID(): cv.declare_id(Select),

View file

@ -28,4 +28,4 @@ async def to_code(config):
cg.add_library("FS", None) cg.add_library("FS", None)
cg.add_library("Update", None) cg.add_library("Update", None)
# https://github.com/esphome/ESPAsyncWebServer/blob/master/library.json # https://github.com/esphome/ESPAsyncWebServer/blob/master/library.json
cg.add_library("esphome/ESPAsyncWebServer-esphome", "2.0.1") cg.add_library("esphome/ESPAsyncWebServer-esphome", "2.1.0")

View file

@ -1,6 +1,6 @@
"""Constants used by esphome.""" """Constants used by esphome."""
__version__ = "2021.11.0b3" __version__ = "2021.11.0b4"
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"

View file

@ -9,6 +9,7 @@
#ifdef USE_WIFI #ifdef USE_WIFI
#include <ESP8266WiFi.h> #include <ESP8266WiFi.h>
#endif #endif
#include <Arduino.h>
#include <osapi.h> #include <osapi.h>
#elif defined(USE_ESP32_FRAMEWORK_ARDUINO) #elif defined(USE_ESP32_FRAMEWORK_ARDUINO)
#include <Esp.h> #include <Esp.h>
@ -430,13 +431,8 @@ void hsv_to_rgb(int hue, float saturation, float value, float &red, float &green
} }
#ifdef USE_ESP8266 #ifdef USE_ESP8266
#ifdef USE_WIFI
IRAM_ATTR InterruptLock::InterruptLock() { xt_state_ = xt_rsil(15); } IRAM_ATTR InterruptLock::InterruptLock() { xt_state_ = xt_rsil(15); }
IRAM_ATTR InterruptLock::~InterruptLock() { xt_wsr_ps(xt_state_); } IRAM_ATTR InterruptLock::~InterruptLock() { xt_wsr_ps(xt_state_); }
#else
IRAM_ATTR InterruptLock::InterruptLock() {}
IRAM_ATTR InterruptLock::~InterruptLock() {}
#endif
#endif #endif
#ifdef USE_ESP32 #ifdef USE_ESP32
IRAM_ATTR InterruptLock::InterruptLock() { portDISABLE_INTERRUPTS(); } IRAM_ATTR InterruptLock::InterruptLock() { portDISABLE_INTERRUPTS(); }

View file

@ -41,7 +41,7 @@ lib_deps =
${common.lib_deps} ${common.lib_deps}
ottowinter/AsyncMqttClient-esphome@0.8.6 ; mqtt ottowinter/AsyncMqttClient-esphome@0.8.6 ; mqtt
ottowinter/ArduinoJson-esphomelib@5.13.3 ; json ottowinter/ArduinoJson-esphomelib@5.13.3 ; json
esphome/ESPAsyncWebServer-esphome@2.0.1 ; web_server_base esphome/ESPAsyncWebServer-esphome@2.1.0 ; web_server_base
fastled/FastLED@3.3.2 ; fastled_base fastled/FastLED@3.3.2 ; fastled_base
mikalhart/TinyGPSPlus@1.0.2 ; gps mikalhart/TinyGPSPlus@1.0.2 ; gps
freekode/TM1651@1.0.1 ; tm1651 freekode/TM1651@1.0.1 ; tm1651

View file

@ -2512,3 +2512,23 @@ teleinfo:
uart_id: uart0 uart_id: uart0
update_interval: 60s update_interval: 60s
historical_mode: true historical_mode: true
number:
- platform: template
id: test_number
state_topic: livingroom/custom_state_topic
command_topic: livingroom/custom_command_topic
min_value: 0
step: 1
max_value: 10
optimistic: true
select:
- platform: template
id: test_select
state_topic: livingroom/custom_state_topic
command_topic: livingroom/custom_command_topic
options:
- one
- two
optimistic: true