mirror of
https://github.com/esphome/esphome.git
synced 2025-08-10 20:29:24 +00:00
Compare commits
101 Commits
2022.6.0b1
...
2022.6.3
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ab86ddcf02 | ||
![]() |
bf8eddb13b | ||
![]() |
e5eaf7a3fe | ||
![]() |
50f32a3aa5 | ||
![]() |
eb878710c1 | ||
![]() |
311980e0e4 | ||
![]() |
df73170e5a | ||
![]() |
ccc13cc9e1 | ||
![]() |
020b2c05c8 | ||
![]() |
4c37c17df1 | ||
![]() |
8f67acadd8 | ||
![]() |
ca13c4c1a6 | ||
![]() |
d0c646c721 | ||
![]() |
8a055675af | ||
![]() |
f329c74a15 | ||
![]() |
7c86f3fa9e | ||
![]() |
203b8b01bf | ||
![]() |
8a1034a92f | ||
![]() |
aa0c2dedd9 | ||
![]() |
8c9948bb56 | ||
![]() |
2d1abaa68e | ||
![]() |
664a3df0b4 | ||
![]() |
9ff893881c | ||
![]() |
94f6c6861a | ||
![]() |
b1d614e6c4 | ||
![]() |
7fceb070e5 | ||
![]() |
5c7c0834c0 | ||
![]() |
f3a25de11d | ||
![]() |
041bef8bcd | ||
![]() |
6e83790308 | ||
![]() |
d2d4eb4eae | ||
![]() |
5942a3898c | ||
![]() |
93421f0fa7 | ||
![]() |
77f322166e | ||
![]() |
f3f6e54818 | ||
![]() |
fb0fec1f25 | ||
![]() |
b66af9fb4d | ||
![]() |
6617d576a7 | ||
![]() |
420dacb22d | ||
![]() |
ae2f6ad4d1 | ||
![]() |
2c28d79bf8 | ||
![]() |
993044c870 | ||
![]() |
a8c1b63edb | ||
![]() |
db7d946e1b | ||
![]() |
fc7348d46d | ||
![]() |
8be2456c7e | ||
![]() |
bb5f7249a6 | ||
![]() |
fc94a5d0ee | ||
![]() |
24029cc918 | ||
![]() |
9a9d5964ee | ||
![]() |
4e4a512107 | ||
![]() |
0729ed538e | ||
![]() |
24b75b7ed6 | ||
![]() |
ec3618ecb8 | ||
![]() |
792a24f38d | ||
![]() |
652e8a015b | ||
![]() |
1ef6fd8fb0 | ||
![]() |
942b0de7fd | ||
![]() |
859cca49d1 | ||
![]() |
8f7ff25624 | ||
![]() |
97aca8e54c | ||
![]() |
95acf19067 | ||
![]() |
3d0899aa58 | ||
![]() |
138d6e505b | ||
![]() |
2748e6ba29 | ||
![]() |
dbd4e927d8 | ||
![]() |
e73d47918f | ||
![]() |
b881bc071e | ||
![]() |
1d0395d1c7 | ||
![]() |
616c787e37 | ||
![]() |
0c4de2bc97 | ||
![]() |
c2f5ac9eba | ||
![]() |
5764c988af | ||
![]() |
ccc2fbfd67 | ||
![]() |
10b4adb8e6 | ||
![]() |
83b7181bcb | ||
![]() |
8886b7e141 | ||
![]() |
7dcc4d030b | ||
![]() |
b9398897c1 | ||
![]() |
657b1c60ae | ||
![]() |
dc54b17778 | ||
![]() |
1fb214165b | ||
![]() |
81b2fd78f5 | ||
![]() |
69002fb1e6 | ||
![]() |
75332a752d | ||
![]() |
09ed1aed93 | ||
![]() |
53d3718028 | ||
![]() |
2b5dce5232 | ||
![]() |
9ad84150aa | ||
![]() |
c0523590b4 | ||
![]() |
c7f091ab10 | ||
![]() |
7479e0aada | ||
![]() |
5bbee1a1fe | ||
![]() |
bdb9546ca3 | ||
![]() |
46af4cad6e | ||
![]() |
76a238912b | ||
![]() |
909a526967 | ||
![]() |
cd6f4fb93f | ||
![]() |
c19458696e | ||
![]() |
318b930e9f | ||
![]() |
9296a078a7 |
@@ -29,6 +29,7 @@ from esphome.const import (
|
||||
DEVICE_CLASS_EMPTY,
|
||||
DEVICE_CLASS_BATTERY,
|
||||
DEVICE_CLASS_BATTERY_CHARGING,
|
||||
DEVICE_CLASS_CARBON_MONOXIDE,
|
||||
DEVICE_CLASS_COLD,
|
||||
DEVICE_CLASS_CONNECTIVITY,
|
||||
DEVICE_CLASS_DOOR,
|
||||
@@ -63,6 +64,7 @@ DEVICE_CLASSES = [
|
||||
DEVICE_CLASS_EMPTY,
|
||||
DEVICE_CLASS_BATTERY,
|
||||
DEVICE_CLASS_BATTERY_CHARGING,
|
||||
DEVICE_CLASS_CARBON_MONOXIDE,
|
||||
DEVICE_CLASS_COLD,
|
||||
DEVICE_CLASS_CONNECTIVITY,
|
||||
DEVICE_CLASS_DOOR,
|
||||
|
@@ -113,6 +113,7 @@ void BLEClient::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t es
|
||||
}
|
||||
case ESP_GATTC_OPEN_EVT: {
|
||||
ESP_LOGV(TAG, "[%s] ESP_GATTC_OPEN_EVT", this->address_str().c_str());
|
||||
this->conn_id = param->open.conn_id;
|
||||
if (param->open.status != ESP_GATT_OK) {
|
||||
ESP_LOGW(TAG, "connect to %s failed, status=%d", this->address_str().c_str(), param->open.status);
|
||||
this->set_states_(espbt::ClientState::IDLE);
|
||||
@@ -122,7 +123,10 @@ void BLEClient::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t es
|
||||
}
|
||||
case ESP_GATTC_CONNECT_EVT: {
|
||||
ESP_LOGV(TAG, "[%s] ESP_GATTC_CONNECT_EVT", this->address_str().c_str());
|
||||
this->conn_id = param->connect.conn_id;
|
||||
if (this->conn_id != param->connect.conn_id) {
|
||||
ESP_LOGD(TAG, "[%s] Unexpected conn_id in CONNECT_EVT: param conn=%d, open conn=%d",
|
||||
this->address_str().c_str(), param->connect.conn_id, this->conn_id);
|
||||
}
|
||||
auto ret = esp_ble_gattc_send_mtu_req(this->gattc_if, param->connect.conn_id);
|
||||
if (ret) {
|
||||
ESP_LOGW(TAG, "esp_ble_gattc_send_mtu_req failed, status=%x", ret);
|
||||
@@ -183,9 +187,10 @@ void BLEClient::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t es
|
||||
descr->uuid.to_string().c_str());
|
||||
break;
|
||||
}
|
||||
uint8_t notify_en = 1;
|
||||
auto status = esp_ble_gattc_write_char_descr(this->gattc_if, this->conn_id, descr->handle, sizeof(notify_en),
|
||||
¬ify_en, ESP_GATT_WRITE_TYPE_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
uint16_t notify_en = 1;
|
||||
auto status =
|
||||
esp_ble_gattc_write_char_descr(this->gattc_if, this->conn_id, descr->handle, sizeof(notify_en),
|
||||
(uint8_t *) ¬ify_en, ESP_GATT_WRITE_TYPE_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "esp_ble_gattc_write_char_descr error, status=%d", status);
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ OVERSAMPLING_OPTIONS = {
|
||||
"4X": Oversampling.OVERSAMPLING_X4,
|
||||
"8X": Oversampling.OVERSAMPLING_X8,
|
||||
"16X": Oversampling.OVERSAMPLING_X16,
|
||||
"32x": Oversampling.OVERSAMPLING_X32,
|
||||
"32X": Oversampling.OVERSAMPLING_X32,
|
||||
}
|
||||
|
||||
IIRFilter = bmp3xx_ns.enum("IIRFilter")
|
||||
|
@@ -79,7 +79,7 @@ async def to_code(config):
|
||||
cg.add(var.set_request_interval(config[CONF_REQUEST_INTERVAL].total_milliseconds))
|
||||
cg.add(var.set_receive_timeout(config[CONF_RECEIVE_TIMEOUT].total_milliseconds))
|
||||
|
||||
cg.add_define("DSMR_GAS_MBUS_ID", config[CONF_GAS_MBUS_ID])
|
||||
cg.add_build_flag("-DDSMR_GAS_MBUS_ID=" + str(config[CONF_GAS_MBUS_ID]))
|
||||
|
||||
# DSMR Parser
|
||||
cg.add_library("glmnet/Dsmr", "0.5")
|
||||
|
@@ -51,6 +51,22 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) {
|
||||
this->state = media_player::MEDIA_PLAYER_STATE_PAUSED;
|
||||
}
|
||||
break;
|
||||
case media_player::MEDIA_PLAYER_COMMAND_VOLUME_UP: {
|
||||
float new_volume = this->volume + 0.1f;
|
||||
if (new_volume > 1.0f)
|
||||
new_volume = 1.0f;
|
||||
this->set_volume_(new_volume);
|
||||
this->unmute_();
|
||||
break;
|
||||
}
|
||||
case media_player::MEDIA_PLAYER_COMMAND_VOLUME_DOWN: {
|
||||
float new_volume = this->volume - 0.1f;
|
||||
if (new_volume < 0.0f)
|
||||
new_volume = 0.0f;
|
||||
this->set_volume_(new_volume);
|
||||
this->unmute_();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this->publish_state();
|
||||
@@ -93,6 +109,10 @@ void I2SAudioMediaPlayer::setup() {
|
||||
this->audio_ = make_unique<Audio>(false);
|
||||
this->audio_->setPinout(this->bclk_pin_, this->lrclk_pin_, this->dout_pin_);
|
||||
this->audio_->forceMono(this->external_dac_channels_ == 1);
|
||||
if (this->mute_pin_ != nullptr) {
|
||||
this->mute_pin_->setup();
|
||||
this->mute_pin_->digital_write(false);
|
||||
}
|
||||
}
|
||||
this->state = media_player::MEDIA_PLAYER_STATE_IDLE;
|
||||
}
|
||||
|
@@ -55,7 +55,7 @@ bool InkbirdIbstH1Mini::parse_device(const esp32_ble_tracker::ESPBTDevice &devic
|
||||
ESP_LOGVV(TAG, "parse_device(): manufacturer data element length is expected to be of length 7");
|
||||
return false;
|
||||
}
|
||||
if (mnf_data.data[6] != 8) {
|
||||
if ((mnf_data.data[6] != 8) && (mnf_data.data[6] != 6)) {
|
||||
ESP_LOGVV(TAG, "parse_device(): unexpected data");
|
||||
return false;
|
||||
}
|
||||
|
@@ -178,7 +178,8 @@ void Logger::pre_setup() {
|
||||
Serial1.setDebugOutput(ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE);
|
||||
#endif
|
||||
break;
|
||||
#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2)
|
||||
#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2) && \
|
||||
!defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case UART_SELECTION_UART2:
|
||||
this->hw_serial_ = &Serial2;
|
||||
Serial2.begin(this->baud_rate_);
|
||||
|
@@ -3,7 +3,7 @@ import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
|
||||
from esphome.automation import maybe_simple_id
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.const import CONF_ID, CONF_ON_STATE, CONF_TRIGGER_ID
|
||||
from esphome.core import CORE
|
||||
from esphome.coroutine import coroutine_with_priority
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
@@ -20,6 +20,9 @@ MediaPlayer = media_player_ns.class_("MediaPlayer")
|
||||
PlayAction = media_player_ns.class_(
|
||||
"PlayAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
PlayMediaAction = media_player_ns.class_(
|
||||
"PlayMediaAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
ToggleAction = media_player_ns.class_(
|
||||
"ToggleAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
@@ -29,10 +32,45 @@ PauseAction = media_player_ns.class_(
|
||||
StopAction = media_player_ns.class_(
|
||||
"StopAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
VolumeUpAction = media_player_ns.class_(
|
||||
"VolumeUpAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
VolumeDownAction = media_player_ns.class_(
|
||||
"VolumeDownAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
VolumeSetAction = media_player_ns.class_(
|
||||
"VolumeSetAction", automation.Action, cg.Parented.template(MediaPlayer)
|
||||
)
|
||||
|
||||
|
||||
CONF_VOLUME = "volume"
|
||||
CONF_ON_IDLE = "on_idle"
|
||||
CONF_ON_PLAY = "on_play"
|
||||
CONF_ON_PAUSE = "on_pause"
|
||||
CONF_MEDIA_URL = "media_url"
|
||||
|
||||
StateTrigger = media_player_ns.class_("StateTrigger", automation.Trigger.template())
|
||||
IdleTrigger = media_player_ns.class_("IdleTrigger", automation.Trigger.template())
|
||||
PlayTrigger = media_player_ns.class_("PlayTrigger", automation.Trigger.template())
|
||||
PauseTrigger = media_player_ns.class_("PauseTrigger", automation.Trigger.template())
|
||||
IsIdleCondition = media_player_ns.class_("IsIdleCondition", automation.Condition)
|
||||
IsPlayingCondition = media_player_ns.class_("IsPlayingCondition", automation.Condition)
|
||||
|
||||
|
||||
async def setup_media_player_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
for conf in config.get(CONF_ON_STATE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for conf in config.get(CONF_ON_IDLE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for conf in config.get(CONF_ON_PLAY, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for conf in config.get(CONF_ON_PAUSE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
|
||||
|
||||
async def register_media_player(var, config):
|
||||
@@ -42,14 +80,54 @@ async def register_media_player(var, config):
|
||||
await setup_media_player_core_(var, config)
|
||||
|
||||
|
||||
MEDIA_PLAYER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.Schema({}))
|
||||
|
||||
|
||||
MEDIA_PLAYER_ACTION_SCHEMA = maybe_simple_id(
|
||||
{cv.Required(CONF_ID): cv.use_id(MediaPlayer)}
|
||||
MEDIA_PLAYER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
||||
{
|
||||
cv.Optional(CONF_ON_STATE): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_IDLE): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(IdleTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_PLAY): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PlayTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_PAUSE): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PauseTrigger),
|
||||
}
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
MEDIA_PLAYER_ACTION_SCHEMA = maybe_simple_id({cv.GenerateID(): cv.use_id(MediaPlayer)})
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"media_player.play_media",
|
||||
PlayMediaAction,
|
||||
cv.maybe_simple_value(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(MediaPlayer),
|
||||
cv.Required(CONF_MEDIA_URL): cv.templatable(cv.url),
|
||||
},
|
||||
key=CONF_MEDIA_URL,
|
||||
),
|
||||
)
|
||||
async def media_player_play_media_action(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
media_url = await cg.templatable(config[CONF_MEDIA_URL], args, cg.std_string)
|
||||
cg.add(var.set_media_url(media_url))
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_action("media_player.play", PlayAction, MEDIA_PLAYER_ACTION_SCHEMA)
|
||||
@automation.register_action(
|
||||
"media_player.toggle", ToggleAction, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
@@ -58,12 +136,43 @@ MEDIA_PLAYER_ACTION_SCHEMA = maybe_simple_id(
|
||||
"media_player.pause", PauseAction, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_action("media_player.stop", StopAction, MEDIA_PLAYER_ACTION_SCHEMA)
|
||||
@automation.register_action(
|
||||
"media_player.volume_up", VolumeUpAction, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_action(
|
||||
"media_player.volume_down", VolumeDownAction, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_condition(
|
||||
"media_player.is_idle", IsIdleCondition, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
)
|
||||
@automation.register_condition(
|
||||
"media_player.is_playing", IsPlayingCondition, MEDIA_PLAYER_ACTION_SCHEMA
|
||||
)
|
||||
async def media_player_action(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
return var
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
"media_player.volume_set",
|
||||
VolumeSetAction,
|
||||
cv.maybe_simple_value(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(MediaPlayer),
|
||||
cv.Required(CONF_VOLUME): cv.templatable(cv.percentage),
|
||||
},
|
||||
key=CONF_VOLUME,
|
||||
),
|
||||
)
|
||||
async def media_player_volume_set_action(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_parented(var, config[CONF_ID])
|
||||
volume = await cg.templatable(config[CONF_VOLUME], args, float)
|
||||
cg.add(var.set_volume(volume))
|
||||
return var
|
||||
|
||||
|
||||
@coroutine_with_priority(100.0)
|
||||
async def to_code(config):
|
||||
cg.add_global(media_player_ns.using)
|
||||
|
@@ -7,28 +7,60 @@ namespace esphome {
|
||||
|
||||
namespace media_player {
|
||||
|
||||
template<typename... Ts> class PlayAction : public Action<Ts...>, public Parented<MediaPlayer> {
|
||||
void play(Ts... x) override {
|
||||
this->parent_->make_call().set_command(MediaPlayerCommand::MEDIA_PLAYER_COMMAND_PLAY).perform();
|
||||
#define MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(ACTION_CLASS, ACTION_COMMAND) \
|
||||
template<typename... Ts> class ACTION_CLASS : public Action<Ts...>, public Parented<MediaPlayer> { \
|
||||
void play(Ts... x) override { \
|
||||
this->parent_->make_call().set_command(MediaPlayerCommand::MEDIA_PLAYER_COMMAND_##ACTION_COMMAND).perform(); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(TRIGGER_CLASS, TRIGGER_STATE) \
|
||||
class TRIGGER_CLASS : public Trigger<> { \
|
||||
public: \
|
||||
explicit TRIGGER_CLASS(MediaPlayer *player) { \
|
||||
player->add_on_state_callback([this, player]() { \
|
||||
if (player->state == MediaPlayerState::MEDIA_PLAYER_STATE_##TRIGGER_STATE) \
|
||||
this->trigger(); \
|
||||
}); \
|
||||
} \
|
||||
};
|
||||
|
||||
MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(PlayAction, PLAY)
|
||||
MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(PauseAction, PAUSE)
|
||||
MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(StopAction, STOP)
|
||||
MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(ToggleAction, TOGGLE)
|
||||
MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(VolumeUpAction, VOLUME_UP)
|
||||
MEDIA_PLAYER_SIMPLE_COMMAND_ACTION(VolumeDownAction, VOLUME_DOWN)
|
||||
|
||||
template<typename... Ts> class PlayMediaAction : public Action<Ts...>, public Parented<MediaPlayer> {
|
||||
TEMPLATABLE_VALUE(std::string, media_url)
|
||||
void play(Ts... x) override { this->parent_->make_call().set_media_url(this->media_url_.value(x...)).perform(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class VolumeSetAction : public Action<Ts...>, public Parented<MediaPlayer> {
|
||||
TEMPLATABLE_VALUE(float, volume)
|
||||
void play(Ts... x) override { this->parent_->make_call().set_volume(this->volume_.value(x...)).perform(); }
|
||||
};
|
||||
|
||||
class StateTrigger : public Trigger<> {
|
||||
public:
|
||||
explicit StateTrigger(MediaPlayer *player) {
|
||||
player->add_on_state_callback([this]() { this->trigger(); });
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts> class ToggleAction : public Action<Ts...>, public Parented<MediaPlayer> {
|
||||
void play(Ts... x) override {
|
||||
this->parent_->make_call().set_command(MediaPlayerCommand::MEDIA_PLAYER_COMMAND_TOGGLE).perform();
|
||||
}
|
||||
MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(IdleTrigger, IDLE)
|
||||
MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(PlayTrigger, PLAYING)
|
||||
MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(PauseTrigger, PAUSED)
|
||||
|
||||
template<typename... Ts> class IsIdleCondition : public Condition<Ts...>, public Parented<MediaPlayer> {
|
||||
public:
|
||||
bool check(Ts... x) override { return this->parent_->state == MediaPlayerState::MEDIA_PLAYER_STATE_IDLE; }
|
||||
};
|
||||
|
||||
template<typename... Ts> class PauseAction : public Action<Ts...>, public Parented<MediaPlayer> {
|
||||
void play(Ts... x) override {
|
||||
this->parent_->make_call().set_command(MediaPlayerCommand::MEDIA_PLAYER_COMMAND_PAUSE).perform();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts> class StopAction : public Action<Ts...>, public Parented<MediaPlayer> {
|
||||
void play(Ts... x) override {
|
||||
this->parent_->make_call().set_command(MediaPlayerCommand::MEDIA_PLAYER_COMMAND_STOP).perform();
|
||||
}
|
||||
template<typename... Ts> class IsPlayingCondition : public Condition<Ts...>, public Parented<MediaPlayer> {
|
||||
public:
|
||||
bool check(Ts... x) override { return this->parent_->state == MediaPlayerState::MEDIA_PLAYER_STATE_PLAYING; }
|
||||
};
|
||||
|
||||
} // namespace media_player
|
||||
|
@@ -20,7 +20,9 @@ enum MediaPlayerCommand : uint8_t {
|
||||
MEDIA_PLAYER_COMMAND_STOP = 2,
|
||||
MEDIA_PLAYER_COMMAND_MUTE = 3,
|
||||
MEDIA_PLAYER_COMMAND_UNMUTE = 4,
|
||||
MEDIA_PLAYER_COMMAND_TOGGLE = 5
|
||||
MEDIA_PLAYER_COMMAND_TOGGLE = 5,
|
||||
MEDIA_PLAYER_COMMAND_VOLUME_UP = 6,
|
||||
MEDIA_PLAYER_COMMAND_VOLUME_DOWN = 7,
|
||||
};
|
||||
const char *media_player_command_to_string(MediaPlayerCommand command);
|
||||
|
||||
|
@@ -108,8 +108,7 @@ void ModbusController::queue_command(const ModbusCommandItem &command) {
|
||||
// check if this commmand is already qeued.
|
||||
// not very effective but the queue is never really large
|
||||
for (auto &item : command_queue_) {
|
||||
if (item->register_address == command.register_address && item->register_count == command.register_count &&
|
||||
item->register_type == command.register_type && item->function_code == command.function_code) {
|
||||
if (item->is_equal(command)) {
|
||||
ESP_LOGW(TAG, "Duplicate modbus command found: type=0x%x address=%u count=%u",
|
||||
static_cast<uint8_t>(command.register_type), command.register_address, command.register_count);
|
||||
// update the payload of the queued command
|
||||
@@ -489,6 +488,15 @@ bool ModbusCommandItem::send() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ModbusCommandItem::is_equal(const ModbusCommandItem &other) {
|
||||
// for custom commands we have to check for identical payloads, since
|
||||
// address/count/type fields will be set to zero
|
||||
return this->function_code == ModbusFunctionCode::CUSTOM
|
||||
? this->payload == other.payload
|
||||
: other.register_address == this->register_address && other.register_count == this->register_count &&
|
||||
other.register_type == this->register_type && other.function_code == this->function_code;
|
||||
}
|
||||
|
||||
void number_to_payload(std::vector<uint16_t> &data, int64_t value, SensorValueType value_type) {
|
||||
switch (value_type) {
|
||||
case SensorValueType::U_WORD:
|
||||
|
@@ -395,6 +395,8 @@ class ModbusCommandItem {
|
||||
ModbusController *modbusdevice, const std::vector<uint16_t> &values,
|
||||
std::function<void(ModbusRegisterType register_type, uint16_t start_address, const std::vector<uint8_t> &data)>
|
||||
&&handler = nullptr);
|
||||
|
||||
bool is_equal(const ModbusCommandItem &other);
|
||||
};
|
||||
|
||||
/** Modbus controller class.
|
||||
|
@@ -187,7 +187,7 @@ void MQTTClientComponent::start_connect_() {
|
||||
|
||||
this->mqtt_backend_.set_credentials(username, password);
|
||||
|
||||
this->mqtt_backend_.set_server((uint32_t) this->ip_, this->credentials_.port);
|
||||
this->mqtt_backend_.set_server(this->credentials_.address.c_str(), this->credentials_.port);
|
||||
if (!this->last_will_.topic.empty()) {
|
||||
this->mqtt_backend_.set_will(this->last_will_.topic.c_str(), this->last_will_.qos, this->last_will_.retain,
|
||||
this->last_will_.payload.c_str());
|
||||
|
@@ -114,6 +114,7 @@ void MQTTFanComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig
|
||||
if (this->state_->get_traits().supports_speed()) {
|
||||
root[MQTT_PERCENTAGE_COMMAND_TOPIC] = this->get_speed_level_command_topic();
|
||||
root[MQTT_PERCENTAGE_STATE_TOPIC] = this->get_speed_level_state_topic();
|
||||
root[MQTT_SPEED_RANGE_MAX] = this->state_->get_traits().supported_speed_count();
|
||||
}
|
||||
}
|
||||
bool MQTTFanComponent::publish_state() {
|
||||
|
@@ -115,7 +115,7 @@ void Nextion::set_backlight_brightness(float brightness) {
|
||||
ESP_LOGD(TAG, "Brightness out of bounds, percentage range 0-1.0");
|
||||
return;
|
||||
}
|
||||
this->add_no_result_to_queue_with_set("backlight_brightness", "dim", static_cast<int>(brightness * 100));
|
||||
this->add_no_result_to_queue_with_printf_("backlight_brightness", "dim=%d", static_cast<int>(brightness * 100));
|
||||
}
|
||||
|
||||
void Nextion::set_auto_wake_on_touch(bool auto_wake) {
|
||||
|
@@ -744,7 +744,8 @@ def rc6_binary_sensor(var, config):
|
||||
var.set_data(
|
||||
cg.StructInitializer(
|
||||
RC6Data,
|
||||
("device", config[CONF_DEVICE]),
|
||||
("mode", 0),
|
||||
("toggle", 0),
|
||||
("address", config[CONF_ADDRESS]),
|
||||
("command", config[CONF_COMMAND]),
|
||||
)
|
||||
|
@@ -140,5 +140,7 @@ async def to_code(config):
|
||||
)
|
||||
)
|
||||
cg.add_library(
|
||||
None, None, "https://github.com/Sensirion/arduino-gas-index-algorithm.git"
|
||||
None,
|
||||
None,
|
||||
"https://github.com/Sensirion/arduino-gas-index-algorithm.git#3.2.1",
|
||||
)
|
||||
|
@@ -170,8 +170,8 @@ bool SGP4xComponent::measure_gas_indices_(int32_t &voc, int32_t &nox) {
|
||||
// much
|
||||
if (this->store_baseline_ && this->seconds_since_last_store_ > SHORTEST_BASELINE_STORE_INTERVAL) {
|
||||
voc_algorithm_.get_states(this->voc_state0_, this->voc_state1_);
|
||||
if ((uint32_t) abs(this->voc_baselines_storage_.state0 - this->voc_state0_) > MAXIMUM_STORAGE_DIFF ||
|
||||
(uint32_t) abs(this->voc_baselines_storage_.state1 - this->voc_state1_) > MAXIMUM_STORAGE_DIFF) {
|
||||
if (std::abs(this->voc_baselines_storage_.state0 - this->voc_state0_) > MAXIMUM_STORAGE_DIFF ||
|
||||
std::abs(this->voc_baselines_storage_.state1 - this->voc_state1_) > MAXIMUM_STORAGE_DIFF) {
|
||||
this->seconds_since_last_store_ = 0;
|
||||
this->voc_baselines_storage_.state0 = this->voc_state0_;
|
||||
this->voc_baselines_storage_.state1 = this->voc_state1_;
|
||||
|
@@ -49,7 +49,7 @@ static const uint16_t SPG41_SELFTEST_TIME = 320; // 320 ms for self test
|
||||
static const uint16_t SGP40_MEASURE_TIME = 30;
|
||||
static const uint16_t SGP41_MEASURE_TIME = 55;
|
||||
// Store anyway if the baseline difference exceeds the max storage diff value
|
||||
const uint32_t MAXIMUM_STORAGE_DIFF = 50;
|
||||
const float MAXIMUM_STORAGE_DIFF = 50.0f;
|
||||
|
||||
class SGP4xComponent;
|
||||
|
||||
@@ -120,8 +120,8 @@ class SGP4xComponent : public PollingComponent, public sensor::Sensor, public se
|
||||
sensor::Sensor *voc_sensor_{nullptr};
|
||||
VOCGasIndexAlgorithm voc_algorithm_;
|
||||
optional<GasTuning> voc_tuning_params_;
|
||||
int32_t voc_state0_;
|
||||
int32_t voc_state1_;
|
||||
float voc_state0_;
|
||||
float voc_state1_;
|
||||
int32_t voc_index_ = 0;
|
||||
|
||||
sensor::Sensor *nox_sensor_{nullptr};
|
||||
|
@@ -353,7 +353,7 @@ void WebServer::handle_sensor_request(AsyncWebServerRequest *request, const UrlM
|
||||
if (obj->get_object_id() != match.id)
|
||||
continue;
|
||||
std::string data = this->sensor_json(obj, obj->state, DETAIL_STATE);
|
||||
request->send(200, "text/json", data.c_str());
|
||||
request->send(200, "application/json", data.c_str());
|
||||
return;
|
||||
}
|
||||
request->send(404);
|
||||
@@ -377,7 +377,7 @@ void WebServer::handle_text_sensor_request(AsyncWebServerRequest *request, const
|
||||
if (obj->get_object_id() != match.id)
|
||||
continue;
|
||||
std::string data = this->text_sensor_json(obj, obj->state, DETAIL_STATE);
|
||||
request->send(200, "text/json", data.c_str());
|
||||
request->send(200, "application/json", data.c_str());
|
||||
return;
|
||||
}
|
||||
request->send(404);
|
||||
@@ -406,7 +406,7 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM
|
||||
|
||||
if (request->method() == HTTP_GET) {
|
||||
std::string data = this->switch_json(obj, obj->state, DETAIL_STATE);
|
||||
request->send(200, "text/json", data.c_str());
|
||||
request->send(200, "application/json", data.c_str());
|
||||
} else if (match.method == "toggle") {
|
||||
this->defer([obj]() { obj->toggle(); });
|
||||
request->send(200);
|
||||
@@ -462,7 +462,7 @@ void WebServer::handle_binary_sensor_request(AsyncWebServerRequest *request, con
|
||||
if (obj->get_object_id() != match.id)
|
||||
continue;
|
||||
std::string data = this->binary_sensor_json(obj, obj->state, DETAIL_STATE);
|
||||
request->send(200, "text/json", data.c_str());
|
||||
request->send(200, "application/json", data.c_str());
|
||||
return;
|
||||
}
|
||||
request->send(404);
|
||||
@@ -490,7 +490,7 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc
|
||||
|
||||
if (request->method() == HTTP_GET) {
|
||||
std::string data = this->fan_json(obj, DETAIL_STATE);
|
||||
request->send(200, "text/json", data.c_str());
|
||||
request->send(200, "application/json", data.c_str());
|
||||
} else if (match.method == "toggle") {
|
||||
this->defer([obj]() { obj->toggle().perform(); });
|
||||
request->send(200);
|
||||
@@ -551,7 +551,7 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa
|
||||
|
||||
if (request->method() == HTTP_GET) {
|
||||
std::string data = this->light_json(obj, DETAIL_STATE);
|
||||
request->send(200, "text/json", data.c_str());
|
||||
request->send(200, "application/json", data.c_str());
|
||||
} else if (match.method == "toggle") {
|
||||
this->defer([obj]() { obj->toggle().perform(); });
|
||||
request->send(200);
|
||||
@@ -630,7 +630,7 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa
|
||||
|
||||
if (request->method() == HTTP_GET) {
|
||||
std::string data = this->cover_json(obj, DETAIL_STATE);
|
||||
request->send(200, "text/json", data.c_str());
|
||||
request->send(200, "application/json", data.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -687,7 +687,7 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM
|
||||
|
||||
if (request->method() == HTTP_GET) {
|
||||
std::string data = this->number_json(obj, obj->state, DETAIL_STATE);
|
||||
request->send(200, "text/json", data.c_str());
|
||||
request->send(200, "application/json", data.c_str());
|
||||
return;
|
||||
}
|
||||
if (match.method != "set") {
|
||||
@@ -741,7 +741,7 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM
|
||||
|
||||
if (request->method() == HTTP_GET) {
|
||||
std::string data = this->select_json(obj, obj->state, DETAIL_STATE);
|
||||
request->send(200, "text/json", data.c_str());
|
||||
request->send(200, "application/json", data.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -788,7 +788,7 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url
|
||||
|
||||
if (request->method() == HTTP_GET) {
|
||||
std::string data = this->climate_json(obj, DETAIL_STATE);
|
||||
request->send(200, "text/json", data.c_str());
|
||||
request->send(200, "application/json", data.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -926,7 +926,7 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat
|
||||
|
||||
if (request->method() == HTTP_GET) {
|
||||
std::string data = this->lock_json(obj, obj->state, DETAIL_STATE);
|
||||
request->send(200, "text/json", data.c_str());
|
||||
request->send(200, "application/json", data.c_str());
|
||||
} else if (match.method == "lock") {
|
||||
this->defer([obj]() { obj->lock(); });
|
||||
request->send(200);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
"""Constants used by esphome."""
|
||||
|
||||
__version__ = "2022.6.0b1"
|
||||
__version__ = "2022.6.3"
|
||||
|
||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||
|
||||
|
@@ -600,7 +600,7 @@ template<class T> class ExternalRAMAllocator {
|
||||
|
||||
ExternalRAMAllocator() = default;
|
||||
ExternalRAMAllocator(Flags flags) : flags_{flags} {}
|
||||
template<class U> constexpr ExternalRAMAllocator(const ExternalRAMAllocator<U> &other) : flags_{other.flags} {}
|
||||
template<class U> constexpr ExternalRAMAllocator(const ExternalRAMAllocator<U> &other) : flags_{other.flags_} {}
|
||||
|
||||
T *allocate(size_t n) {
|
||||
size_t size = n * sizeof(T);
|
||||
|
@@ -40,7 +40,7 @@ lib_deps =
|
||||
wjtje/qr-code-generator-library@1.7.0 ; qr_code
|
||||
functionpointer/arduino-MLX90393@1.0.0 ; mlx90393
|
||||
; This is using the repository until a new release is published to PlatformIO
|
||||
https://github.com/Sensirion/arduino-gas-index-algorithm.git ; Sensirion Gas Index Algorithm Arduino Library
|
||||
https://github.com/Sensirion/arduino-gas-index-algorithm.git#3.2.1 ; Sensirion Gas Index Algorithm Arduino Library
|
||||
build_flags =
|
||||
-DESPHOME_LOG_LEVEL=ESPHOME_LOG_LEVEL_VERY_VERBOSE
|
||||
src_filter =
|
||||
|
@@ -613,3 +613,20 @@ media_player:
|
||||
i2s_dout_pin: GPIO25
|
||||
i2s_bclk_pin: GPIO27
|
||||
mute_pin: GPIO14
|
||||
on_state:
|
||||
- media_player.play:
|
||||
- media_player.play_media: http://localhost/media.mp3
|
||||
- media_player.play_media: !lambda 'return "http://localhost/media.mp3";'
|
||||
on_idle:
|
||||
- media_player.pause:
|
||||
on_play:
|
||||
- media_player.stop:
|
||||
on_pause:
|
||||
- media_player.toggle:
|
||||
- wait_until:
|
||||
media_player.is_idle:
|
||||
- wait_until:
|
||||
media_player.is_playing:
|
||||
- media_player.volume_up:
|
||||
- media_player.volume_down:
|
||||
- media_player.volume_set: 50%
|
||||
|
Reference in New Issue
Block a user