Merge remote-tracking branch 'upstream/fix-time-timezone-offset' into integration

This commit is contained in:
J. Nick Koston
2026-03-19 18:58:04 -10:00
7 changed files with 81 additions and 40 deletions
+1 -1
View File
@@ -1 +1 @@
44c877ff43765562ac8298902bf2208799643b77facf09c1c0c3c8c4e17187eb
9f5d763f95ff720024f3fdddba2fad3801e2bfe00b7cc2124e6d68c17d3504c6
+37
View File
@@ -5,6 +5,30 @@
namespace esphome {
namespace sdl {
int Sdl::get_width() {
switch (this->rotation_) {
case display::DISPLAY_ROTATION_90_DEGREES:
case display::DISPLAY_ROTATION_270_DEGREES:
return this->get_height_internal();
case display::DISPLAY_ROTATION_0_DEGREES:
case display::DISPLAY_ROTATION_180_DEGREES:
default:
return this->get_width_internal();
}
}
int Sdl::get_height() {
switch (this->rotation_) {
case display::DISPLAY_ROTATION_0_DEGREES:
case display::DISPLAY_ROTATION_180_DEGREES:
return this->get_height_internal();
case display::DISPLAY_ROTATION_90_DEGREES:
case display::DISPLAY_ROTATION_270_DEGREES:
default:
return this->get_width_internal();
}
}
void Sdl::setup() {
SDL_Init(SDL_INIT_VIDEO);
this->window_ = SDL_CreateWindow(App.get_name().c_str(), this->pos_x_, this->pos_y_, this->width_, this->height_,
@@ -49,6 +73,19 @@ void Sdl::draw_pixel_at(int x, int y, Color color) {
if (!this->get_clipping().inside(x, y))
return;
if (this->rotation_ == display::DISPLAY_ROTATION_180_DEGREES) {
x = this->width_ - x - 1;
y = this->height_ - y - 1;
} else if (this->rotation_ == display::DISPLAY_ROTATION_90_DEGREES) {
auto tmp = x;
x = this->width_ - y - 1;
y = tmp;
} else if (this->rotation_ == display::DISPLAY_ROTATION_270_DEGREES) {
auto tmp = y;
y = this->height_ - x - 1;
x = tmp;
}
SDL_Rect rect{x, y, 1, 1};
auto data = (display::ColorUtil::color_to_565(color, display::COLOR_ORDER_RGB));
SDL_UpdateTexture(this->texture_, &rect, &data, 2);
+2 -2
View File
@@ -33,8 +33,8 @@ class Sdl : public display::Display {
this->pos_x_ = pos_x;
this->pos_y_ = pos_y;
}
int get_width() override { return this->width_; }
int get_height() override { return this->height_; }
int get_width() override;
int get_height() override;
float get_setup_priority() const override { return setup_priority::HARDWARE; }
void dump_config() override { LOG_DISPLAY("", "SDL", this); }
template<typename F> void add_key_listener(int32_t keycode, F &&callback) {
@@ -16,17 +16,15 @@ static const char *const TAG = "template.alarm_control_panel";
TemplateAlarmControlPanel::TemplateAlarmControlPanel(){};
#ifdef USE_BINARY_SENSOR
void TemplateAlarmControlPanel::add_sensor(binary_sensor::BinarySensor *sensor, uint16_t flags, AlarmSensorType type) {
// Save the flags and type. Assign a store index for the per sensor data type.
SensorDataStore sd;
sd.last_chime_state = false;
void TemplateAlarmControlPanel::add_sensor(binary_sensor::BinarySensor *sensor, uint8_t flags, AlarmSensorType type) {
// Save the sensor pointer, flags, and type in the per-sensor info structure.
AlarmSensor alarm_sensor;
alarm_sensor.sensor = sensor;
alarm_sensor.info.flags = flags;
alarm_sensor.info.type = type;
alarm_sensor.info.store_index = this->next_store_index_++;
alarm_sensor.info.chime_active = false;
alarm_sensor.info.auto_bypassed = false;
this->sensors_.push_back(alarm_sensor);
this->sensor_data_.push_back(sd);
};
// Alarm sensor type strings indexed by AlarmSensorType enum (0-3): DELAYED, INSTANT, DELAYED_FOLLOWER, INSTANT_ALWAYS
@@ -55,7 +53,7 @@ void TemplateAlarmControlPanel::dump_config() {
(this->trigger_time_ / 1000), this->get_supported_features());
#ifdef USE_BINARY_SENSOR
for (const auto &alarm_sensor : this->sensors_) {
const uint16_t flags = alarm_sensor.info.flags;
const uint8_t flags = alarm_sensor.info.flags;
ESP_LOGCONFIG(TAG,
" Binary Sensor:\n"
" Name: %s\n"
@@ -95,7 +93,7 @@ void TemplateAlarmControlPanel::loop() {
delay = this->arming_night_time_;
}
if ((millis() - this->last_update_) > delay) {
this->bypass_before_arming();
this->auto_bypass_sensors_();
this->publish_state(this->desired_state_);
}
return;
@@ -117,26 +115,25 @@ void TemplateAlarmControlPanel::loop() {
#ifdef USE_BINARY_SENSOR
// Test all of the sensors regardless of the alarm panel state
for (const auto &alarm_sensor : this->sensors_) {
const auto &info = alarm_sensor.info;
for (auto &alarm_sensor : this->sensors_) {
auto &info = alarm_sensor.info;
auto *sensor = alarm_sensor.sensor;
// Check for chime zones
if (info.flags & BINARY_SENSOR_MODE_CHIME) {
// Look for the transition from closed to open
if ((!this->sensor_data_[info.store_index].last_chime_state) && (sensor->state)) {
if ((!info.chime_active) && (sensor->state)) {
// Must be disarmed to chime
if (this->current_state_ == ACP_STATE_DISARMED) {
this->chime_callback_.call();
}
}
// Record the sensor state change
this->sensor_data_[info.store_index].last_chime_state = sensor->state;
info.chime_active = sensor->state;
}
// Check for faulted sensors
if (sensor->state) {
// Skip if auto bypassed
if (std::count(this->bypassed_sensor_indicies_.begin(), this->bypassed_sensor_indicies_.end(),
info.store_index) == 1) {
if (info.auto_bypassed) {
continue;
}
// Skip if bypass armed home
@@ -239,23 +236,33 @@ void TemplateAlarmControlPanel::arm_(optional<std::string> code, alarm_control_p
if (delay > 0) {
this->publish_state(ACP_STATE_ARMING);
} else {
this->bypass_before_arming();
this->auto_bypass_sensors_();
this->publish_state(state);
}
}
void TemplateAlarmControlPanel::bypass_before_arming() {
void TemplateAlarmControlPanel::auto_bypass_sensors_() {
#ifdef USE_BINARY_SENSOR
for (const auto &alarm_sensor : this->sensors_) {
for (auto &alarm_sensor : this->sensors_) {
auto &info = alarm_sensor.info;
auto *sensor = alarm_sensor.sensor;
// Check for faulted bypass_auto sensors and remove them from monitoring
if ((alarm_sensor.info.flags & BINARY_SENSOR_MODE_BYPASS_AUTO) && (alarm_sensor.sensor->state)) {
ESP_LOGW(TAG, "'%s' is faulted and will be automatically bypassed", alarm_sensor.sensor->get_name().c_str());
this->bypassed_sensor_indicies_.push_back(alarm_sensor.info.store_index);
if ((info.flags & BINARY_SENSOR_MODE_BYPASS_AUTO) && (sensor->state)) {
ESP_LOGW(TAG, "'%s' is faulted and will be automatically bypassed", sensor->get_name().c_str());
info.auto_bypassed = true;
}
}
#endif
}
void TemplateAlarmControlPanel::clear_auto_bypassed_sensors_() {
#ifdef USE_BINARY_SENSOR
for (auto &alarm_sensor : this->sensors_) {
alarm_sensor.info.auto_bypassed = false;
}
#endif
}
void TemplateAlarmControlPanel::control(const AlarmControlPanelCall &call) {
auto opt_state = call.get_state();
if (opt_state) {
@@ -273,9 +280,7 @@ void TemplateAlarmControlPanel::control(const AlarmControlPanelCall &call) {
}
this->desired_state_ = ACP_STATE_DISARMED;
this->publish_state(ACP_STATE_DISARMED);
#ifdef USE_BINARY_SENSOR
this->bypassed_sensor_indicies_.clear();
#endif
this->clear_auto_bypassed_sensors_();
} else if (state == ACP_STATE_TRIGGERED) {
this->publish_state(ACP_STATE_TRIGGERED);
} else if (state == ACP_STATE_PENDING) {
@@ -18,7 +18,7 @@
namespace esphome::template_ {
#ifdef USE_BINARY_SENSOR
enum BinarySensorFlags : uint16_t {
enum BinarySensorFlags : uint8_t {
BINARY_SENSOR_MODE_NORMAL = 1 << 0,
BINARY_SENSOR_MODE_BYPASS_ARMED_HOME = 1 << 1,
BINARY_SENSOR_MODE_BYPASS_ARMED_NIGHT = 1 << 2,
@@ -41,14 +41,11 @@ enum TemplateAlarmControlPanelRestoreMode {
};
#ifdef USE_BINARY_SENSOR
struct SensorDataStore {
bool last_chime_state;
};
struct SensorInfo {
uint16_t flags;
uint8_t flags;
AlarmSensorType type;
uint8_t store_index;
bool chime_active;
bool auto_bypassed;
};
struct AlarmSensor {
@@ -68,7 +65,9 @@ class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControl
bool get_requires_code_to_arm() const override { return this->requires_code_to_arm_; }
bool get_all_sensors_ready() { return this->sensors_ready_; };
void set_restore_mode(TemplateAlarmControlPanelRestoreMode restore_mode) { this->restore_mode_ = restore_mode; }
void bypass_before_arming();
// Remove before 2026.10.0
ESPDEPRECATED("bypass_before_arming() is deprecated and will be removed in 2026.10.0", "2026.4.0")
void bypass_before_arming() { this->auto_bypass_sensors_(); }
#ifdef USE_BINARY_SENSOR
/** Initialize the sensors vector with the specified capacity.
@@ -83,7 +82,7 @@ class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControl
* @param flags The OR of BinarySensorFlags for the sensor.
* @param type The sensor type which determines its triggering behaviour.
*/
void add_sensor(binary_sensor::BinarySensor *sensor, uint16_t flags = 0,
void add_sensor(binary_sensor::BinarySensor *sensor, uint8_t flags = 0,
AlarmSensorType type = ALARM_SENSOR_TYPE_DELAYED);
#endif
@@ -141,11 +140,6 @@ class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControl
#ifdef USE_BINARY_SENSOR
// List of binary sensors with their alarm-specific info
FixedVector<AlarmSensor> sensors_;
// a list of automatically bypassed sensors
std::vector<uint8_t> bypassed_sensor_indicies_;
// Per sensor data store
std::vector<SensorDataStore> sensor_data_;
uint8_t next_store_index_ = 0;
#endif
TemplateAlarmControlPanelRestoreMode restore_mode_{};
@@ -170,6 +164,8 @@ class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControl
bool is_code_valid_(optional<std::string> code);
void arm_(optional<std::string> code, alarm_control_panel::AlarmControlPanelState state, uint32_t delay);
void auto_bypass_sensors_();
void clear_auto_bypassed_sensors_();
};
} // namespace esphome::template_
+2
View File
@@ -1,5 +1,7 @@
#pragma once
#include "esphome/core/defines.h"
#include <cstdint>
#include <cstdlib>
#include <cstring>
+1
View File
@@ -546,6 +546,7 @@ extends = common
platform = platformio/native
lib_deps =
esphome/noise-c@0.1.11 ; used by api
lvgl/lvgl@9.5.0 ; lvgl
build_flags =
${common.build_flags}
-DUSE_HOST