Skip to content

Commit

Permalink
Add Timezone Select
Browse files Browse the repository at this point in the history
  • Loading branch information
AzonInc committed Nov 1, 2024
1 parent 55b9043 commit 79ff8cf
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 11 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -352,4 +352,7 @@ MigrationBackup/
# ESPHome
__pycache__
.esphome
/*.yaml
/*.yaml

# VSCode
.vscode
65 changes: 65 additions & 0 deletions components/nuki_lock/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
CONF_FOB_ACTION_1_SELECT = "fob_action_1"
CONF_FOB_ACTION_2_SELECT = "fob_action_2"
CONF_FOB_ACTION_3_SELECT = "fob_action_3"
CONF_TIMEZONE_SELECT = "timezone"

CONF_LED_BRIGHTNESS_NUMBER = "led_brightness"
CONF_SECURITY_PIN_NUMBER = "security_pin"
Expand All @@ -71,6 +72,56 @@
"Intelligent",
]

CONF_TIMEZONE_SELECT_OPTIONS = [
"Africa/Cairo",
"Africa/Lagos",
"Africa/Maputo",
"Africa/Nairobi",
"America/Anchorage",
"America/Argentina/Buenos_Aires",
"America/Chicago",
"America/Denver",
"America/Halifax",
"America/Los_Angeles",
"America/Manaus",
"America/Mexico_City",
"America/New_York",
"America/Phoenix",
"America/Regina",
"America/Santiago",
"America/Sao_Paulo",
"America/St_Johns",
"Asia/Bangkok",
"Asia/Dubai",
"Asia/Hong_Kong",
"Asia/Jerusalem",
"Asia/Karachi",
"Asia/Kathmandu",
"Asia/Kolkata",
"Asia/Riyadh",
"Asia/Seoul",
"Asia/Shanghai",
"Asia/Tehran",
"Asia/Tokyo",
"Asia/Yangon",
"Australia/Adelaide",
"Australia/Brisbane",
"Australia/Darwin",
"Australia/Hobart",
"Australia/Perth",
"Australia/Sydney",
"Europe/Berlin",
"Europe/Helsinki",
"Europe/Istanbul",
"Europe/London",
"Europe/Moscow",
"Pacific/Auckland",
"Pacific/Guam",
"Pacific/Honolulu",
"Pacific/Pago_Pago",
"None"
]

CONF_PAIRING_MODE_TIMEOUT = "pairing_mode_timeout"
CONF_EVENT = "event"

Expand Down Expand Up @@ -103,6 +154,7 @@
NukiLockFobAction1Select = nuki_lock_ns.class_("NukiLockFobAction1Select", select.Select, cg.Component)
NukiLockFobAction2Select = nuki_lock_ns.class_("NukiLockFobAction2Select", select.Select, cg.Component)
NukiLockFobAction3Select = nuki_lock_ns.class_("NukiLockFobAction3Select", select.Select, cg.Component)
NukiLockTimeZoneSelect = nuki_lock_ns.class_("NukiLockTimeZoneSelect", select.Select, cg.Component)

NukiLockUnpairAction = nuki_lock_ns.class_(
"NukiLockUnpairAction", automation.Action
Expand Down Expand Up @@ -270,6 +322,11 @@
entity_category=ENTITY_CATEGORY_CONFIG,
icon="mdi:gesture-tap",
),
cv.Optional(CONF_TIMEZONE_SELECT): select.select_schema(
NukiLockTimeZoneSelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon="mdi:map-clock",
),

cv.Optional(CONF_PAIRING_MODE_TIMEOUT, default="300s"): cv.positive_time_period_seconds,
cv.Optional(CONF_EVENT, default="nuki"): cv.string,
Expand Down Expand Up @@ -458,6 +515,14 @@ async def to_code(config):
await cg.register_parented(sel, config[CONF_ID])
cg.add(var.set_fob_action_3_select(sel))

if timezone := config.get(CONF_TIMEZONE_SELECT):
sel = await select.new_select(
timezone,
options=[CONF_TIMEZONE_SELECT_OPTIONS],
)
await cg.register_parented(sel, config[CONF_ID])
cg.add(var.set_timezone_select(sel))


# Callback
for conf in config.get(CONF_ON_PAIRING_MODE_ON, []):
Expand Down
145 changes: 137 additions & 8 deletions components/nuki_lock/nuki_lock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "esphome/components/api/custom_api_device.h"
#endif

#include <unordered_map>

#include "nuki_lock.h"

namespace esphome {
Expand Down Expand Up @@ -60,7 +62,7 @@ std::string NukiLockComponent::nuki_doorsensor_to_string(Nuki::DoorSensorState n
}
}

NukiLock::ButtonPressAction NukiLockComponent::nuki_button_press_action_to_enum(std::string str)
NukiLock::ButtonPressAction NukiLockComponent::button_press_action_to_enum(std::string str)
{
if (str == "No Action") return NukiLock::ButtonPressAction::NoAction;
if (str == "Intelligent") return NukiLock::ButtonPressAction::Intelligent;
Expand All @@ -69,10 +71,10 @@ NukiLock::ButtonPressAction NukiLockComponent::nuki_button_press_action_to_enum(
if (str == "Unlatch") return NukiLock::ButtonPressAction::Unlatch;
if (str == "Lock n Go") return NukiLock::ButtonPressAction::LockNgo;
if (str == "Show Status") return NukiLock::ButtonPressAction::ShowStatus;
return (NukiLock::ButtonPressAction)0xff;
return NukiLock::ButtonPressAction::NoAction;
}

const char* NukiLockComponent::nuki_button_press_action_to_string(NukiLock::ButtonPressAction action)
const char* NukiLockComponent::button_press_action_to_string(NukiLock::ButtonPressAction action)
{
switch (action)
{
Expand All @@ -94,7 +96,7 @@ uint8_t NukiLockComponent::fob_action_to_int(std::string str)
if(str == "Lock") return 2;
if(str == "Lock n Go") return 3;
if(str == "Intelligent") return 4;
return 99;
return 0;
}

std::string NukiLockComponent::fob_action_to_string(uint8_t action)
Expand All @@ -107,6 +109,118 @@ std::string NukiLockComponent::fob_action_to_string(uint8_t action)
return "No Action";
}

Nuki::TimeZoneId NukiLockComponent::nuki_timezone_to_enum(std:string str)
{
static const std::unordered_map<std::string, Nuki::TimeZoneId> timezoneMap = {
{"Africa/Cairo", Nuki::TimeZoneId::Africa_Cairo},
{"Africa/Lagos", Nuki::TimeZoneId::Africa_Lagos},
{"Africa/Maputo", Nuki::TimeZoneId::Africa_Maputo},
{"Africa/Nairobi", Nuki::TimeZoneId::Africa_Nairobi},
{"America/Anchorage", Nuki::TimeZoneId::America_Anchorage},
{"America/Argentina/Buenos_Aires", Nuki::TimeZoneId::America_Argentina_Buenos_Aires},
{"America/Chicago", Nuki::TimeZoneId::America_Chicago},
{"America/Denver", Nuki::TimeZoneId::America_Denver},
{"America/Halifax", Nuki::TimeZoneId::America_Halifax},
{"America/Los_Angeles", Nuki::TimeZoneId::America_Los_Angeles},
{"America/Manaus", Nuki::TimeZoneId::America_Manaus},
{"America/Mexico_City", Nuki::TimeZoneId::America_Mexico_City},
{"America/New_York", Nuki::TimeZoneId::America_New_York},
{"America/Phoenix", Nuki::TimeZoneId::America_Phoenix},
{"America/Regina", Nuki::TimeZoneId::America_Regina},
{"America/Santiago", Nuki::TimeZoneId::America_Santiago},
{"America/Sao_Paulo", Nuki::TimeZoneId::America_Sao_Paulo},
{"America/St_Johns", Nuki::TimeZoneId::America_St_Johns},
{"Asia/Bangkok", Nuki::TimeZoneId::Asia_Bangkok},
{"Asia/Dubai", Nuki::TimeZoneId::Asia_Dubai},
{"Asia/Hong_Kong", Nuki::TimeZoneId::Asia_Hong_Kong},
{"Asia/Jerusalem", Nuki::TimeZoneId::Asia_Jerusalem},
{"Asia/Karachi", Nuki::TimeZoneId::Asia_Karachi},
{"Asia/Kathmandu", Nuki::TimeZoneId::Asia_Kathmandu},
{"Asia/Kolkata", Nuki::TimeZoneId::Asia_Kolkata},
{"Asia/Riyadh", Nuki::TimeZoneId::Asia_Riyadh},
{"Asia/Seoul", Nuki::TimeZoneId::Asia_Seoul},
{"Asia/Shanghai", Nuki::TimeZoneId::Asia_Shanghai},
{"Asia/Tehran", Nuki::TimeZoneId::Asia_Tehran},
{"Asia/Tokyo", Nuki::TimeZoneId::Asia_Tokyo},
{"Asia/Yangon", Nuki::TimeZoneId::Asia_Yangon},
{"Australia/Adelaide", Nuki::TimeZoneId::Australia_Adelaide},
{"Australia/Brisbane", Nuki::TimeZoneId::Australia_Brisbane},
{"Australia/Darwin", Nuki::TimeZoneId::Australia_Darwin},
{"Australia/Hobart", Nuki::TimeZoneId::Australia_Hobart},
{"Australia/Perth", Nuki::TimeZoneId::Australia_Perth},
{"Australia/Sydney", Nuki::TimeZoneId::Australia_Sydney},
{"Europe/Berlin", Nuki::TimeZoneId::Europe_Berlin},
{"Europe/Helsinki", Nuki::TimeZoneId::Europe_Helsinki},
{"Europe/Istanbul", Nuki::TimeZoneId::Europe_Istanbul},
{"Europe/London", Nuki::TimeZoneId::Europe_London},
{"Europe/Moscow", Nuki::TimeZoneId::Europe_Moscow},
{"Pacific/Auckland", Nuki::TimeZoneId::Pacific_Auckland},
{"Pacific/Guam", Nuki::TimeZoneId::Pacific_Guam},
{"Pacific/Honolulu", Nuki::TimeZoneId::Pacific_Honolulu},
{"Pacific/Pago_Pago", Nuki::TimeZoneId::Pacific_Pago_Pago},
{"None", Nuki::TimeZoneId::None}
};

auto it = timezoneMap.find(str);
return (it != timezoneMap.end()) ? it->second : Nuki::TimeZoneId::None;
}

std::string NukiLockComponent::nuki_timezone_to_string(Nuki::TimeZoneId timezoneId)
{
static const std::unordered_map<Nuki::TimeZoneId, std::string> idToStringMap = {
{Nuki::TimeZoneId::Africa_Cairo, "Africa/Cairo"},
{Nuki::TimeZoneId::Africa_Lagos, "Africa/Lagos"},
{Nuki::TimeZoneId::Africa_Maputo, "Africa/Maputo"},
{Nuki::TimeZoneId::Africa_Nairobi, "Africa/Nairobi"},
{Nuki::TimeZoneId::America_Anchorage, "America/Anchorage"},
{Nuki::TimeZoneId::America_Argentina_Buenos_Aires, "America/Argentina/Buenos_Aires"},
{Nuki::TimeZoneId::America_Chicago, "America/Chicago"},
{Nuki::TimeZoneId::America_Denver, "America/Denver"},
{Nuki::TimeZoneId::America_Halifax, "America/Halifax"},
{Nuki::TimeZoneId::America_Los_Angeles, "America/Los_Angeles"},
{Nuki::TimeZoneId::America_Manaus, "America/Manaus"},
{Nuki::TimeZoneId::America_Mexico_City, "America/Mexico_City"},
{Nuki::TimeZoneId::America_New_York, "America/New_York"},
{Nuki::TimeZoneId::America_Phoenix, "America/Phoenix"},
{Nuki::TimeZoneId::America_Regina, "America/Regina"},
{Nuki::TimeZoneId::America_Santiago, "America/Santiago"},
{Nuki::TimeZoneId::America_Sao_Paulo, "America/Sao_Paulo"},
{Nuki::TimeZoneId::America_St_Johns, "America/St_Johns"},
{Nuki::TimeZoneId::Asia_Bangkok, "Asia/Bangkok"},
{Nuki::TimeZoneId::Asia_Dubai, "Asia/Dubai"},
{Nuki::TimeZoneId::Asia_Hong_Kong, "Asia/Hong_Kong"},
{Nuki::TimeZoneId::Asia_Jerusalem, "Asia/Jerusalem"},
{Nuki::TimeZoneId::Asia_Karachi, "Asia/Karachi"},
{Nuki::TimeZoneId::Asia_Kathmandu, "Asia/Kathmandu"},
{Nuki::TimeZoneId::Asia_Kolkata, "Asia/Kolkata"},
{Nuki::TimeZoneId::Asia_Riyadh, "Asia/Riyadh"},
{Nuki::TimeZoneId::Asia_Seoul, "Asia/Seoul"},
{Nuki::TimeZoneId::Asia_Shanghai, "Asia/Shanghai"},
{Nuki::TimeZoneId::Asia_Tehran, "Asia/Tehran"},
{Nuki::TimeZoneId::Asia_Tokyo, "Asia/Tokyo"},
{Nuki::TimeZoneId::Asia_Yangon, "Asia/Yangon"},
{Nuki::TimeZoneId::Australia_Adelaide, "Australia/Adelaide"},
{Nuki::TimeZoneId::Australia_Brisbane, "Australia/Brisbane"},
{Nuki::TimeZoneId::Australia_Darwin, "Australia/Darwin"},
{Nuki::TimeZoneId::Australia_Hobart, "Australia/Hobart"},
{Nuki::TimeZoneId::Australia_Perth, "Australia/Perth"},
{Nuki::TimeZoneId::Australia_Sydney, "Australia/Sydney"},
{Nuki::TimeZoneId::Europe_Berlin, "Europe/Berlin"},
{Nuki::TimeZoneId::Europe_Helsinki, "Europe/Helsinki"},
{Nuki::TimeZoneId::Europe_Istanbul, "Europe/Istanbul"},
{Nuki::TimeZoneId::Europe_London, "Europe/London"},
{Nuki::TimeZoneId::Europe_Moscow, "Europe/Moscow"},
{Nuki::TimeZoneId::Pacific_Auckland, "Pacific/Auckland"},
{Nuki::TimeZoneId::Pacific_Guam, "Pacific/Guam"},
{Nuki::TimeZoneId::Pacific_Honolulu, "Pacific/Honolulu"},
{Nuki::TimeZoneId::Pacific_Pago_Pago, "Pacific/Pago_Pago"},
{Nuki::TimeZoneId::None, "None"}
};

auto it = idToStringMap.find(timezoneId);
return (it != idToStringMap.end()) ? it->second : "None";
}

void NukiLockComponent::save_settings()
{
NukiLockSettings settings {
Expand Down Expand Up @@ -218,6 +332,8 @@ void NukiLockComponent::update_config() {
this->fob_action_2_select_->publish_state(this->fob_action_to_string(config.fobAction2));
if (this->fob_action_3_select_ != nullptr)
this->fob_action_3_select_->publish_state(this->fob_action_to_string(config.fobAction3));
if (this->timezone_select_ != nullptr)
this->timezone_select_->publish_state(this->timezone_to_string(config.timeZoneId));
#endif

} else {
Expand Down Expand Up @@ -264,10 +380,10 @@ void NukiLockComponent::update_advanced_config() {
#endif
#ifdef USE_SELECT
if (this->single_button_press_action_select_ != nullptr)
this->single_button_press_action_select_->publish_state(this->nuki_button_press_action_to_string(advanced_config.singleButtonPressAction));
this->single_button_press_action_select_->publish_state(this->button_press_action_to_string(advanced_config.singleButtonPressAction));

if (this->double_button_press_action_select_ != nullptr)
this->double_button_press_action_select_->publish_state(this->nuki_button_press_action_to_string(advanced_config.doubleButtonPressAction));
this->double_button_press_action_select_->publish_state(this->button_press_action_to_string(advanced_config.doubleButtonPressAction));
#endif

} else {
Expand Down Expand Up @@ -971,6 +1087,7 @@ void NukiLockComponent::dump_config() {
LOG_SELECT(TAG, "Fob Action 1", this->fob_action_1_select_);
LOG_SELECT(TAG, "Fob Action 2", this->fob_action_2_select_);
LOG_SELECT(TAG, "Fob Action 3", this->fob_action_3_select_);
LOG_SELECT(TAG, "Timezone", this->timezone_select_);
#endif
}

Expand Down Expand Up @@ -1034,13 +1151,13 @@ void NukiLockComponent::set_config_select(std::string config, const std::string
// Update Config
if(config == "single_button_press_action")
{
NukiLock::ButtonPressAction action = this->nuki_button_press_action_to_enum(value);
NukiLock::ButtonPressAction action = this->button_press_action_to_enum(value);
cmd_result = this->nuki_lock_.setSingleButtonPressAction(action);
is_advanced = true;
}
else if(config == "double_button_press_action")
{
NukiLock::ButtonPressAction action = this->nuki_button_press_action_to_enum(value);
NukiLock::ButtonPressAction action = this->button_press_action_to_enum(value);
cmd_result = this->nuki_lock_.setDoubleButtonPressAction(action);
is_advanced = true;
}
Expand Down Expand Up @@ -1068,6 +1185,11 @@ void NukiLockComponent::set_config_select(std::string config, const std::string
cmd_result = this->nuki_lock_.setFobAction(3, action);
}
}
else if(config == "timezone")
{
Nuki::TimeZoneId tzid = this->timezone_to_enum(value);
cmd_result = this->nuki_lock_.setTimeZoneId(tzid);
}

if(cmd_result == Nuki::CmdResult::Success)
{
Expand All @@ -1091,6 +1213,10 @@ void NukiLockComponent::set_config_select(std::string config, const std::string
{
if (this->fob_action_3_select_ != nullptr) this->fob_action_3_select_->publish_state(value);
}
else if(config == "timezone")
{
if (this->timezone_select_ != nullptr) this->timezone_select_->publish_state(value);
}

this->config_update_ = !is_advanced;
this->advanced_config_update_ = is_advanced;
Expand Down Expand Up @@ -1256,6 +1382,9 @@ void NukiLockFobAction2Select::control(const std::string &action) {
void NukiLockFobAction3Select::control(const std::string &action) {
this->parent_->set_config_select("fob_action_3", action);
}
void NukiLockTimeZoneSelect::control(const std::string &zone) {
this->parent_->set_config_select("timezone", zone);
}
#endif
#ifdef USE_SWITCH
void NukiLockPairingModeSwitch::write_state(bool state) {
Expand Down
16 changes: 14 additions & 2 deletions components/nuki_lock/nuki_lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class NukiLockComponent : public lock::Lock, public PollingComponent, public Nuk
SUB_SELECT(fob_action_1)
SUB_SELECT(fob_action_2)
SUB_SELECT(fob_action_3)
SUB_SELECT(timezone)
#endif
#ifdef USE_BUTTON
SUB_BUTTON(unpair)
Expand Down Expand Up @@ -136,8 +137,11 @@ class NukiLockComponent : public lock::Lock, public PollingComponent, public Nuk
uint8_t fob_action_to_int(std::string str);
std::string fob_action_to_string(uint8_t action);

NukiLock::ButtonPressAction nuki_button_press_action_to_enum(std::string str);
const char* nuki_button_press_action_to_string(NukiLock::ButtonPressAction action);
NukiLock::ButtonPressAction button_press_action_to_enum(std::string str);
const char* button_press_action_to_string(NukiLock::ButtonPressAction action);

Nuki::TimeZoneId timezone_to_enum(std:string str);
std::string timezone_to_string(Nuki::TimeZoneId timezoneId);

void unpair();
void set_pairing_mode(bool enabled);
Expand Down Expand Up @@ -304,12 +308,20 @@ class NukiLockFobAction2Select : public select::Select, public Parented<NukiLock
protected:
void control(const std::string &value) override;
};

class NukiLockFobAction3Select : public select::Select, public Parented<NukiLockComponent> {
public:
NukiLockFobAction3Select() = default;
protected:
void control(const std::string &value) override;
};

class NukiLockTimeZoneSelect : public select::Select, public Parented<NukiLockComponent> {
public:
NukiLockTimeZoneSelect() = default;
protected:
void control(const std::string &value) override;
};
#endif

#ifdef USE_SWITCH
Expand Down

0 comments on commit 79ff8cf

Please sign in to comment.