Compare commits
2 commits
10efb46153
...
aa371c22a4
Author | SHA1 | Date | |
---|---|---|---|
aa371c22a4 | |||
e85874cccf |
3 changed files with 98 additions and 1 deletions
|
@ -81,6 +81,52 @@ void PCF85063Component::write_time() {
|
||||||
this->write_rtc_();
|
this->write_rtc_();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PCF85063Component::write_nvram(uint8_t data) {
|
||||||
|
this->pcf85063_.reg.nvram = data;
|
||||||
|
this->write_bytes(0x03, &this->pcf85063_.raw[0x03], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t PCF85063Component::read_nvram() {
|
||||||
|
this->read_bytes(0x03, &this->pcf85063_.raw[0x03], 1);
|
||||||
|
return this->pcf85063_.reg.nvram;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TIMER_CLOCK_MINUTE 60 15300 1m 4h15m
|
||||||
|
TIMER_CLOCK_SECOND 1 255 1s 4m15s
|
||||||
|
*/
|
||||||
|
bool PCF85063Component::set_timer_interval(uint16_t interval_seconds) {
|
||||||
|
if (interval_seconds < 256) {
|
||||||
|
pcf85063_.reg.timer_clock_frequency = TIMER_CLOCK_SECOND;
|
||||||
|
pcf85063_.reg.timer_value = interval_seconds;
|
||||||
|
pcf85063_.reg.timer_enable = true;
|
||||||
|
return this->write_timer_();
|
||||||
|
} else if (interval_seconds > 15300) {
|
||||||
|
ESP_LOGE(TAG, "Specified interval is longer than max allowed, clamping to 4h15m.");
|
||||||
|
interval_seconds = 15300;
|
||||||
|
}
|
||||||
|
div_t dm = div(interval_seconds, 60);
|
||||||
|
if (dm.rem) {
|
||||||
|
ESP_LOGI(TAG, "Interval out of seconds range, rounding down to closest whole minute.");
|
||||||
|
}
|
||||||
|
|
||||||
|
pcf85063_.reg.timer_clock_frequency = TIMER_CLOCK_MINUTE;
|
||||||
|
pcf85063_.reg.timer_value = dm.quot;
|
||||||
|
pcf85063_.reg.timer_enable = true;
|
||||||
|
return this->write_timer_();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PCF85063Component::write_timer_() {
|
||||||
|
if (!this->write_bytes(0x10, &this->pcf85063_.raw[0x03], 2)) {
|
||||||
|
ESP_LOGE(TAG, "Can't write I2C data.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ESP_LOGD(TAG, "Write timer %s %0u CLOCK=%0u IR=%s %0u",
|
||||||
|
ONOFF(pcf85063_.reg.timer_enable), pcf85063_.reg.timer_value, pcf85063_.reg.timer_clock_frequency,
|
||||||
|
ONOFF(pcf85063_.reg.timer_interrupt_enable), pcf85063_.reg.timer_interrupt_mode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool PCF85063Component::read_rtc_() {
|
bool PCF85063Component::read_rtc_() {
|
||||||
if (!this->read_bytes(0, this->pcf85063_.raw, sizeof(this->pcf85063_.raw))) {
|
if (!this->read_bytes(0, this->pcf85063_.raw, sizeof(this->pcf85063_.raw))) {
|
||||||
ESP_LOGE(TAG, "Can't read I2C data.");
|
ESP_LOGE(TAG, "Can't read I2C data.");
|
||||||
|
|
|
@ -27,8 +27,14 @@ class PCF85063Component : public time::RealTimeClock, public i2c::I2CDevice {
|
||||||
float get_setup_priority() const override;
|
float get_setup_priority() const override;
|
||||||
void read_time();
|
void read_time();
|
||||||
void write_time();
|
void write_time();
|
||||||
|
void write_nvram(uint8_t);
|
||||||
|
uint8_t read_nvram();
|
||||||
|
|
||||||
|
bool set_timer_interval(uint16_t interval);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool write_timer_();
|
||||||
bool read_rtc_();
|
bool read_rtc_();
|
||||||
bool write_rtc_();
|
bool write_rtc_();
|
||||||
union PCF85063Reg {
|
union PCF85063Reg {
|
||||||
|
@ -133,6 +139,16 @@ class PCF85063Component : public time::RealTimeClock, public i2c::I2CDevice {
|
||||||
} pcf85063_;
|
} pcf85063_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> class StartTimerAction : public Action<Ts...>, public Parented<PCF85063Component> {
|
||||||
|
public:
|
||||||
|
TEMPLATABLE_VALUE(uint16_t, timer_seconds);
|
||||||
|
void play(Ts... x) override {
|
||||||
|
this->parent_->pcf85063_.reg.timer_interrupt_enable = true;
|
||||||
|
this->parent_->pcf85063_.reg.timer_interrupt_mode = TIMER_INTERRUPT_MODE_FLAG;
|
||||||
|
this->parent_->set_timer_interval(this->timer_seconds_.value(x...));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename... Ts> class WriteAction : public Action<Ts...>, public Parented<PCF85063Component> {
|
template<typename... Ts> class WriteAction : public Action<Ts...>, public Parented<PCF85063Component> {
|
||||||
public:
|
public:
|
||||||
void play(Ts... x) override { this->parent_->write_time(); }
|
void play(Ts... x) override { this->parent_->write_time(); }
|
||||||
|
|
|
@ -2,7 +2,7 @@ import esphome.config_validation as cv
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
from esphome.components import i2c, time
|
from esphome.components import i2c, time
|
||||||
from esphome.const import CONF_ID
|
from esphome.const import CONF_ID, CONF_INTERVAL
|
||||||
|
|
||||||
|
|
||||||
CODEOWNERS = ["@brogon"]
|
CODEOWNERS = ["@brogon"]
|
||||||
|
@ -13,6 +13,7 @@ PCF85063Component = pcf85063_ns.class_(
|
||||||
)
|
)
|
||||||
WriteAction = pcf85063_ns.class_("WriteAction", automation.Action)
|
WriteAction = pcf85063_ns.class_("WriteAction", automation.Action)
|
||||||
ReadAction = pcf85063_ns.class_("ReadAction", automation.Action)
|
ReadAction = pcf85063_ns.class_("ReadAction", automation.Action)
|
||||||
|
StartTimerAction = pcf85063_ns.class_("StartTimerAction", automation.Action)
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = time.TIME_SCHEMA.extend(
|
CONFIG_SCHEMA = time.TIME_SCHEMA.extend(
|
||||||
|
@ -52,6 +53,40 @@ async def pcf85063_read_time_to_code(config, action_id, template_arg, args):
|
||||||
return var
|
return var
|
||||||
|
|
||||||
|
|
||||||
|
def validate_timer_seconds(value):
|
||||||
|
value: cv.TimePeriodSeconds = cv.positive_time_period_seconds(value)
|
||||||
|
min_interval = cv.TimePeriod(seconds=1)
|
||||||
|
max_interval = cv.TimePeriod(minutes=255)
|
||||||
|
|
||||||
|
if value < min_interval:
|
||||||
|
raise cv.Invalid(
|
||||||
|
f"This timer interval is not possible, please choose a larger interval (at least {min_interval})"
|
||||||
|
)
|
||||||
|
if value > max_interval:
|
||||||
|
raise cv.Invalid(
|
||||||
|
f"This timer interval is not possible, please choose a lower interval (at most {max_interval})"
|
||||||
|
)
|
||||||
|
return value
|
||||||
|
|
||||||
|
@automation.register_action(
|
||||||
|
"pcf85063.start_timer",
|
||||||
|
StartTimerAction,
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.use_id(PCF85063Component),
|
||||||
|
cv.Required(CONF_INTERVAL): cv.templatable(validate_timer_seconds),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
async def pcf85063_start_timer_to_code(config, action_id, template_arg, args):
|
||||||
|
var = cg.new_Pvariable(action_id, template_arg)
|
||||||
|
|
||||||
|
template_ = await cg.templatable(config[CONF_INTERVAL], args, cv.TimePeriodSeconds)
|
||||||
|
cg.add(var.start_timer(template_))
|
||||||
|
|
||||||
|
await cg.register_parented(var, config[CONF_ID])
|
||||||
|
return var
|
||||||
|
|
||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue