Skip to content

Commit

Permalink
update common components for esphome 2024.4
Browse files Browse the repository at this point in the history
  • Loading branch information
KaufHA committed Apr 12, 2024
1 parent 26bb34a commit c75cdf1
Show file tree
Hide file tree
Showing 10 changed files with 360 additions and 18 deletions.
14 changes: 9 additions & 5 deletions components/esp8266/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
KEY_TARGET_FRAMEWORK,
KEY_TARGET_PLATFORM,
PLATFORM_ESP8266,
)
)
from esphome.core import CORE, coroutine_with_priority
import esphome.config_validation as cv
import esphome.codegen as cg
Expand Down Expand Up @@ -83,20 +83,22 @@ def _format_framework_arduino_version(ver: cv.Version) -> str:
# The default/recommended arduino framework version
# - https://github.com/esp8266/Arduino/releases
# - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-arduinoespressif8266
RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 0, 2)
RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 1, 2)
# The platformio/espressif8266 version to use for arduino 2 framework versions
# - https://github.com/platformio/platform-espressif8266/releases
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif8266
ARDUINO_2_PLATFORM_VERSION = cv.Version(2, 6, 3)
# for arduino 3 framework versions
ARDUINO_3_PLATFORM_VERSION = cv.Version(3, 2, 0)
# for arduino 4 framework versions
ARDUINO_4_PLATFORM_VERSION = cv.Version(4, 2, 1)


def _arduino_check_versions(value):
value = value.copy()
lookups = {
"dev": (cv.Version(3, 0, 2), "https://github.com/esp8266/Arduino.git"),
"latest": (cv.Version(3, 0, 2), None),
"dev": (cv.Version(3, 1, 2), "https://github.com/esp8266/Arduino.git"),
"latest": (cv.Version(3, 1, 2), None),
"recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None),
}

Expand All @@ -116,7 +118,9 @@ def _arduino_check_versions(value):

platform_version = value.get(CONF_PLATFORM_VERSION)
if platform_version is None:
if version >= cv.Version(3, 0, 0):
if version >= cv.Version(3, 1, 0):
platform_version = _parse_platform_version(str(ARDUINO_4_PLATFORM_VERSION))
elif version >= cv.Version(3, 0, 0):
platform_version = _parse_platform_version(str(ARDUINO_3_PLATFORM_VERSION))
elif version >= cv.Version(2, 5, 0):
platform_version = _parse_platform_version(str(ARDUINO_2_PLATFORM_VERSION))
Expand Down
35 changes: 34 additions & 1 deletion components/template/datetime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
CONF_OPTIMISTIC,
CONF_RESTORE_VALUE,
CONF_SET_ACTION,
CONF_DAY,
CONF_HOUR,
CONF_MINUTE,
CONF_MONTH,
CONF_SECOND,
CONF_TYPE,
CONF_YEAR,
)

from esphome.core import coroutine_with_priority
Expand All @@ -20,6 +27,10 @@
"TemplateDate", datetime.DateEntity, cg.PollingComponent
)

TemplateTime = template_ns.class_(
"TemplateTime", datetime.TimeEntity, cg.PollingComponent
)


def validate(config):
config = config.copy()
Expand Down Expand Up @@ -60,6 +71,13 @@ def validate(config):
cv.Optional(CONF_INITIAL_VALUE): cv.date_time(allowed_time=False),
}
),
"TIME": datetime.time_schema(TemplateTime)
.extend(_BASE_SCHEMA)
.extend(
{
cv.Optional(CONF_INITIAL_VALUE): cv.date_time(allowed_date=False),
}
),
},
upper=True,
),
Expand All @@ -82,7 +100,22 @@ async def to_code(config):
cg.add(var.set_restore_value(config[CONF_RESTORE_VALUE]))

if initial_value := config.get(CONF_INITIAL_VALUE):
cg.add(var.set_initial_value(initial_value))
if config[CONF_TYPE] == "DATE":
date_struct = cg.StructInitializer(
cg.ESPTime,
("day_of_month", initial_value[CONF_DAY]),
("month", initial_value[CONF_MONTH]),
("year", initial_value[CONF_YEAR]),
)
cg.add(var.set_initial_value(date_struct))
elif config[CONF_TYPE] == "TIME":
time_struct = cg.StructInitializer(
cg.ESPTime,
("second", initial_value[CONF_SECOND]),
("minute", initial_value[CONF_MINUTE]),
("hour", initial_value[CONF_HOUR]),
)
cg.add(var.set_initial_value(time_struct))

if CONF_SET_ACTION in config:
await automation.build_automation(
Expand Down
111 changes: 111 additions & 0 deletions components/template/datetime/template_time.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#include "template_time.h"

#ifdef USE_DATETIME_TIME

#include "esphome/core/log.h"

namespace esphome {
namespace template_ {

static const char *const TAG = "template.time";

void TemplateTime::setup() {
if (this->f_.has_value())
return;

ESPTime state{};

if (!this->restore_value_) {
state = this->initial_value_;
} else {
datetime::TimeEntityRestoreState temp;
this->pref_ =
global_preferences->make_preference<datetime::TimeEntityRestoreState>(194434060U ^ this->get_object_id_hash());
if (this->pref_.load(&temp)) {
temp.apply(this);
return;
} else {
// set to inital value if loading from pref failed
state = this->initial_value_;
}
}

this->hour_ = state.hour;
this->minute_ = state.minute;
this->second_ = state.second;
this->publish_state();
}

void TemplateTime::update() {
if (!this->f_.has_value())
return;

auto val = (*this->f_)();
if (!val.has_value())
return;

this->hour_ = val->hour;
this->minute_ = val->minute;
this->second_ = val->second;
this->publish_state();
}

void TemplateTime::control(const datetime::TimeCall &call) {
bool has_hour = call.get_hour().has_value();
bool has_minute = call.get_minute().has_value();
bool has_second = call.get_second().has_value();

ESPTime value = {};
if (has_hour)
value.hour = *call.get_hour();

if (has_minute)
value.minute = *call.get_minute();

if (has_second)
value.second = *call.get_second();

this->set_trigger_->trigger(value);

if (this->optimistic_) {
if (has_hour)
this->hour_ = *call.get_hour();
if (has_minute)
this->minute_ = *call.get_minute();
if (has_second)
this->second_ = *call.get_second();
this->publish_state();
}

if (this->restore_value_) {
datetime::TimeEntityRestoreState temp = {};
if (has_hour) {
temp.hour = *call.get_hour();
} else {
temp.hour = this->hour_;
}
if (has_minute) {
temp.minute = *call.get_minute();
} else {
temp.minute = this->minute_;
}
if (has_second) {
temp.second = *call.get_second();
} else {
temp.second = this->second_;
}

this->pref_.save(&temp);
}
}

void TemplateTime::dump_config() {
LOG_DATETIME_TIME("", "Template Time", this);
ESP_LOGCONFIG(TAG, " Optimistic: %s", YESNO(this->optimistic_));
LOG_UPDATE_INTERVAL(this);
}

} // namespace template_
} // namespace esphome

#endif // USE_DATETIME_TIME
46 changes: 46 additions & 0 deletions components/template/datetime/template_time.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once

#include "esphome/core/defines.h"

#ifdef USE_DATETIME_TIME

#include "esphome/components/datetime/time_entity.h"
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
#include "esphome/core/preferences.h"
#include "esphome/core/time.h"

namespace esphome {
namespace template_ {

class TemplateTime : public datetime::TimeEntity, public PollingComponent {
public:
void set_template(std::function<optional<ESPTime>()> &&f) { this->f_ = f; }

void setup() override;
void update() override;
void dump_config() override;
float get_setup_priority() const override { return setup_priority::HARDWARE; }

Trigger<ESPTime> *get_set_trigger() const { return this->set_trigger_; }
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }

void set_initial_value(ESPTime initial_value) { this->initial_value_ = initial_value; }
void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; }

protected:
void control(const datetime::TimeCall &call) override;

bool optimistic_{false};
ESPTime initial_value_{};
bool restore_value_{false};
Trigger<ESPTime> *set_trigger_ = new Trigger<ESPTime>();
optional<std::function<optional<ESPTime>()>> f_;

ESPPreferenceObject pref_;
};

} // namespace template_
} // namespace esphome

#endif // USE_DATETIME_TIME
Loading

0 comments on commit c75cdf1

Please sign in to comment.