Merge branch 'dev' into nvds-new-espnow

This commit is contained in:
NP v/d Spek 2024-10-14 04:56:42 +02:00 committed by GitHub
commit 951ee4e5dc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 102 additions and 52 deletions

View file

@ -1,6 +1,6 @@
from esphome import automation from esphome import automation
import esphome.codegen as cg import esphome.codegen as cg
from esphome.components import mqtt from esphome.components import mqtt, web_server
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import ( from esphome.const import (
CONF_DEVICE_CLASS, CONF_DEVICE_CLASS,
@ -11,6 +11,7 @@ from esphome.const import (
CONF_MQTT_ID, CONF_MQTT_ID,
CONF_ON_EVENT, CONF_ON_EVENT,
CONF_TRIGGER_ID, CONF_TRIGGER_ID,
CONF_WEB_SERVER,
DEVICE_CLASS_BUTTON, DEVICE_CLASS_BUTTON,
DEVICE_CLASS_DOORBELL, DEVICE_CLASS_DOORBELL,
DEVICE_CLASS_EMPTY, DEVICE_CLASS_EMPTY,
@ -40,17 +41,21 @@ EventTrigger = event_ns.class_("EventTrigger", automation.Trigger.template())
validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_")
EVENT_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMPONENT_SCHEMA).extend( EVENT_SCHEMA = (
{ cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTEventComponent), .extend(cv.MQTT_COMPONENT_SCHEMA)
cv.GenerateID(): cv.declare_id(Event), .extend(
cv.Optional(CONF_DEVICE_CLASS): validate_device_class, {
cv.Optional(CONF_ON_EVENT): automation.validate_automation( cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTEventComponent),
{ cv.GenerateID(): cv.declare_id(Event),
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(EventTrigger), cv.Optional(CONF_DEVICE_CLASS): validate_device_class,
} cv.Optional(CONF_ON_EVENT): automation.validate_automation(
), {
} cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(EventTrigger),
}
),
}
)
) )
_UNDEF = object() _UNDEF = object()
@ -97,6 +102,9 @@ async def setup_event_core_(var, config, *, event_types: list[str]):
mqtt_ = cg.new_Pvariable(mqtt_id, var) mqtt_ = cg.new_Pvariable(mqtt_id, var)
await mqtt.register_mqtt_component(mqtt_, config) await mqtt.register_mqtt_component(mqtt_, config)
if web_server_config := config.get(CONF_WEB_SERVER):
await web_server.add_entity_config(var, web_server_config)
async def register_event(var, config, *, event_types: list[str]): async def register_event(var, config, *, event_types: list[str]):
if not CORE.has_id(config[CONF_ID]): if not CORE.has_id(config[CONF_ID]):

View file

@ -64,46 +64,46 @@ uint16_t shelly_dimmer_checksum(const uint8_t *buf, int len) {
return std::accumulate<decltype(buf), uint16_t>(buf, buf + len, 0); return std::accumulate<decltype(buf), uint16_t>(buf, buf + len, 0);
} }
bool ShellyDimmer::is_running_configured_version() const {
return this->version_major_ == USE_SHD_FIRMWARE_MAJOR_VERSION &&
this->version_minor_ == USE_SHD_FIRMWARE_MINOR_VERSION;
}
void ShellyDimmer::handle_firmware() {
// Reset the STM32 and check the firmware version.
this->reset_normal_boot_();
this->send_command_(SHELLY_DIMMER_PROTO_CMD_VERSION, nullptr, 0);
ESP_LOGI(TAG, "STM32 current firmware version: %d.%d, desired version: %d.%d", this->version_major_,
this->version_minor_, USE_SHD_FIRMWARE_MAJOR_VERSION, USE_SHD_FIRMWARE_MINOR_VERSION);
if (!is_running_configured_version()) {
#ifdef USE_SHD_FIRMWARE_DATA
if (!this->upgrade_firmware_()) {
ESP_LOGW(TAG, "Failed to upgrade firmware");
this->mark_failed();
return;
}
this->reset_normal_boot_();
this->send_command_(SHELLY_DIMMER_PROTO_CMD_VERSION, nullptr, 0);
if (!is_running_configured_version()) {
ESP_LOGE(TAG, "STM32 firmware upgrade already performed, but version is still incorrect");
this->mark_failed();
return;
}
#else
ESP_LOGW(TAG, "Firmware version mismatch, put 'update: true' in the yaml to flash an update.");
#endif
}
}
void ShellyDimmer::setup() { void ShellyDimmer::setup() {
this->pin_nrst_->setup(); this->pin_nrst_->setup();
this->pin_boot0_->setup(); this->pin_boot0_->setup();
ESP_LOGI(TAG, "Initializing Shelly Dimmer..."); ESP_LOGI(TAG, "Initializing Shelly Dimmer...");
// Reset the STM32 and check the firmware version. this->handle_firmware();
for (int i = 0; i < 2; i++) {
this->reset_normal_boot_();
this->send_command_(SHELLY_DIMMER_PROTO_CMD_VERSION, nullptr, 0);
ESP_LOGI(TAG, "STM32 current firmware version: %d.%d, desired version: %d.%d", this->version_major_,
this->version_minor_, USE_SHD_FIRMWARE_MAJOR_VERSION, USE_SHD_FIRMWARE_MINOR_VERSION);
if (this->version_major_ != USE_SHD_FIRMWARE_MAJOR_VERSION ||
this->version_minor_ != USE_SHD_FIRMWARE_MINOR_VERSION) {
#ifdef USE_SHD_FIRMWARE_DATA
// Update firmware if needed.
ESP_LOGW(TAG, "Unsupported STM32 firmware version, flashing");
if (i > 0) {
// Upgrade was already performed but the reported version is still not right.
ESP_LOGE(TAG, "STM32 firmware upgrade already performed, but version is still incorrect");
this->mark_failed();
return;
}
if (!this->upgrade_firmware_()) {
ESP_LOGW(TAG, "Failed to upgrade firmware");
this->mark_failed();
return;
}
// Firmware upgrade completed, do the checks again.
continue;
#else
ESP_LOGW(TAG, "Firmware version mismatch, put 'update: true' in the yaml to flash an update.");
this->mark_failed();
return;
#endif
}
break;
}
this->send_settings_(); this->send_settings_();
// Do an immediate poll to refresh current state. // Do an immediate poll to refresh current state.

View file

@ -20,6 +20,8 @@ class ShellyDimmer : public PollingComponent, public light::LightOutput, public
public: public:
float get_setup_priority() const override { return setup_priority::LATE; } float get_setup_priority() const override { return setup_priority::LATE; }
bool is_running_configured_version() const;
void handle_firmware();
void setup() override; void setup() override;
void update() override; void update() override;
void dump_config() override; void dump_config() override;

View file

@ -18,8 +18,8 @@ void Touchscreen::attach_interrupt_(InternalGPIOPin *irq_pin, esphome::gpio::Int
void Touchscreen::call_setup() { void Touchscreen::call_setup() {
if (this->display_ != nullptr) { if (this->display_ != nullptr) {
this->display_width_ = this->display_->get_native_width(); this->display_width_ = this->display_->get_width();
this->display_height_ = this->display_->get_native_height(); this->display_height_ = this->display_->get_height();
} }
PollingComponent::call_setup(); PollingComponent::call_setup();
} }

View file

@ -1441,9 +1441,26 @@ std::string WebServer::alarm_control_panel_json(alarm_control_panel::AlarmContro
void WebServer::on_event(event::Event *obj, const std::string &event_type) { void WebServer::on_event(event::Event *obj, const std::string &event_type) {
this->events_.send(this->event_json(obj, event_type, DETAIL_STATE).c_str(), "state"); this->events_.send(this->event_json(obj, event_type, DETAIL_STATE).c_str(), "state");
} }
void WebServer::handle_event_request(AsyncWebServerRequest *request, const UrlMatch &match) {
for (event::Event *obj : App.get_events()) {
if (obj->get_object_id() != match.id)
continue;
if (request->method() == HTTP_GET && match.method.empty()) {
auto detail = DETAIL_STATE;
auto *param = request->getParam("detail");
if (param && param->value() == "all") {
detail = DETAIL_ALL;
}
std::string data = this->event_json(obj, "", detail);
request->send(200, "application/json", data.c_str());
return;
}
}
request->send(404);
}
std::string WebServer::event_json(event::Event *obj, const std::string &event_type, JsonDetail start_config) { std::string WebServer::event_json(event::Event *obj, const std::string &event_type, JsonDetail start_config) {
return json::build_json([obj, event_type, start_config](JsonObject root) { return json::build_json([this, obj, event_type, start_config](JsonObject root) {
set_json_id(root, obj, "event-" + obj->get_object_id(), start_config); set_json_id(root, obj, "event-" + obj->get_object_id(), start_config);
if (!event_type.empty()) { if (!event_type.empty()) {
root["event_type"] = event_type; root["event_type"] = event_type;
@ -1454,6 +1471,12 @@ std::string WebServer::event_json(event::Event *obj, const std::string &event_ty
event_types.add(event_type); event_types.add(event_type);
} }
root["device_class"] = obj->get_device_class(); root["device_class"] = obj->get_device_class();
if (this->sorting_entitys_.find(obj) != this->sorting_entitys_.end()) {
root["sorting_weight"] = this->sorting_entitys_[obj].weight;
if (this->sorting_groups_.find(this->sorting_entitys_[obj].group_id) != this->sorting_groups_.end()) {
root["sorting_group"] = this->sorting_groups_[this->sorting_entitys_[obj].group_id].name;
}
}
} }
}); });
} }
@ -1645,6 +1668,11 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) {
return true; return true;
#endif #endif
#ifdef USE_EVENT
if (request->method() == HTTP_GET && match.domain == "event")
return true;
#endif
#ifdef USE_UPDATE #ifdef USE_UPDATE
if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "update") if ((request->method() == HTTP_POST || request->method() == HTTP_GET) && match.domain == "update")
return true; return true;

View file

@ -322,6 +322,9 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
#ifdef USE_EVENT #ifdef USE_EVENT
void on_event(event::Event *obj, const std::string &event_type) override; void on_event(event::Event *obj, const std::string &event_type) override;
/// Handle a event request under '/event<id>'.
void handle_event_request(AsyncWebServerRequest *request, const UrlMatch &match);
/// Dump the event details with its value as a JSON string. /// Dump the event details with its value as a JSON string.
std::string event_json(event::Event *obj, const std::string &event_type, JsonDetail start_config); std::string event_json(event::Event *obj, const std::string &event_type, JsonDetail start_config);
#endif #endif

View file

@ -2,6 +2,15 @@
set -e set -e
help() {
echo "Usage: $0 [-e <config|compile|clean>] [-c <string>] [-t <string>]" 1>&2
echo 1>&2
echo " - e - Parameter for esphome command. Default compile. Common alternative is config." 1>&2
echo " - c - Component folder name to test. Default *. E.g. '-c logger'." 1>&2
echo " - t - Target name to test. Put '-t list' to display all possibilities. E.g. '-t esp32-s2-idf-51'." 1>&2
exit 1
}
# Parse parameter: # Parse parameter:
# - `e` - Parameter for `esphome` command. Default `compile`. Common alternative is `config`. # - `e` - Parameter for `esphome` command. Default `compile`. Common alternative is `config`.
# - `c` - Component folder name to test. Default `*`. # - `c` - Component folder name to test. Default `*`.
@ -13,7 +22,7 @@ do
e) esphome_command=${OPTARG};; e) esphome_command=${OPTARG};;
c) target_component=${OPTARG};; c) target_component=${OPTARG};;
t) requested_target_platform=${OPTARG};; t) requested_target_platform=${OPTARG};;
\?) echo "Usage: $0 [-e <config|compile|clean>] [-c <string>] [-t <string>]" 1>&2; exit 1;; \?) help;;
esac esac
done done
@ -24,8 +33,8 @@ if ! [ -d "./tests/test_build_components/build" ]; then
fi fi
start_esphome() { start_esphome() {
if [ -n "$requested_target_platform" ] && [ "$requested_target_platform" != "$target_platform" ]; then if [ -n "$requested_target_platform" ] && [ "$requested_target_platform" != "$target_platform_with_version" ]; then
echo "Skiping $target_platform" echo "Skipping $target_platform_with_version"
return return
fi fi
# create dynamic yaml file in `build` folder. # create dynamic yaml file in `build` folder.