Skip to content

Commit

Permalink
Add Ultra Pairing Mode and Settings
Browse files Browse the repository at this point in the history
  • Loading branch information
AzonInc committed Feb 12, 2025
1 parent 4c85ec0 commit f104e0f
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 85 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ lock:
name: "Nuki Daylight Saving Time"
auto_battery_type_detection_enabled:
name: "Nuki Automatic Battery Type Detection"
slow_speed_during_night_mode_enabled:
name: "Nuki Slow Speed During Night Mode"
# Optional: Select Inputs
single_buton_press_action:
name: "Nuki Button: Single Press Action"
Expand All @@ -124,6 +126,8 @@ lock:
name: "Nuki Advertising Mode"
battery_type:
name: "Nuki Battery Type"
motor_speed:
name: "Nuki Motor Speed"
# Optional: Buttons
unpair:
name: "Nuki Unpair Device"
Expand Down Expand Up @@ -228,6 +232,8 @@ lock:
name: "Nuki Daylight Saving Time"
auto_battery_type_detection_enabled:
name: "Nuki Automatic Battery Type Detection"
slow_speed_during_night_mode_enabled:
name: "Nuki Slow Speed During Night Mode"
# Optional: Select Inputs
single_buton_press_action:
name: "Nuki Button: Single Press Action"
Expand All @@ -245,6 +251,8 @@ lock:
name: "Nuki Advertising Mode"
battery_type:
name: "Nuki Battery Type"
motor_speed:
name: "Nuki Motor Speed"
# Optional: Buttons
unpair:
name: "Nuki Unpair Device"
Expand Down Expand Up @@ -458,7 +466,8 @@ context:
- Single Lock
- Daylight Saving Time
- Automatic Updates
- Automatic Battery Type Detection
- Automatic Battery Type Detection (Smart Lock Gen 1-4)
- Slow Speed During Night Mode (Smart Lock Ultra)

**Select Input:**
- Single Button Press Action
Expand All @@ -468,7 +477,8 @@ context:
- Fob Action 3
- Timezone
- Advertising Mode
- Battery Type
- Battery Type (Smart Lock Gen 1-4)
- Motor Speed (Smart Lock Ultra)

**Number Input:**
- LED Brightness
Expand Down
63 changes: 34 additions & 29 deletions components/nuki_lock/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
CONF_PAIRING_MODE_TIMEOUT = "pairing_mode_timeout"
CONF_PAIRING_AS_APP = "pairing_as_app"
CONF_SECURITY_PIN = "security_pin"
CONF_ULTRA_PAIRING_MODE = "ultra_pairing_mode"
CONF_ALT_CONNECT_MODE = "alternative_connect_mode"
CONF_QUERY_INTERVAL_CONFIG = "query_interval_config"
CONF_QUERY_INTERVAL_AUTH_DATA = "query_interval_auth_data"
Expand Down Expand Up @@ -193,7 +194,7 @@
NukiLockSingleLockEnabledSwitch = nuki_lock_ns.class_("NukiLockSingleLockEnabledSwitch", switch.Switch, cg.Component)
NukiLockDstModeEnabledSwitch = nuki_lock_ns.class_("NukiLockDstModeEnabledSwitch", switch.Switch, cg.Component)
NukiLockAutoBatteryTypeDetectionEnabledSwitch = nuki_lock_ns.class_("NukiLockAutoBatteryTypeDetectionEnabledSwitch", switch.Switch, cg.Component)
#NukiLockSlowSpeedDuringNightModeEnabledSwitch = nuki_lock_ns.class_("NukiLockSlowSpeedDuringNightModeEnabledSwitch", switch.Switch, cg.Component)
NukiLockSlowSpeedDuringNightModeEnabledSwitch = nuki_lock_ns.class_("NukiLockSlowSpeedDuringNightModeEnabledSwitch", switch.Switch, cg.Component)

NukiLockLedBrightnessNumber = nuki_lock_ns.class_("NukiLockLedBrightnessNumber", number.Number, cg.Component)
NukiLockTimeZoneOffsetNumber = nuki_lock_ns.class_("NukiLockTimeZoneOffsetNumber", number.Number, cg.Component)
Expand All @@ -207,7 +208,7 @@
NukiLockTimeZoneSelect = nuki_lock_ns.class_("NukiLockTimeZoneSelect", select.Select, cg.Component)
NukiLockAdvertisingModeSelect = nuki_lock_ns.class_("NukiLockAdvertisingModeSelect", select.Select, cg.Component)
NukiLockBatteryTypeSelect = nuki_lock_ns.class_("NukiLockBatteryTypeSelect", select.Select, cg.Component)
#NukiLockMotorSpeedSelect = nuki_lock_ns.class_("NukiLockMotorSpeedSelect", select.Select, cg.Component)
NukiLockMotorSpeedSelect = nuki_lock_ns.class_("NukiLockMotorSpeedSelect", select.Select, cg.Component)

NukiLockUnpairAction = nuki_lock_ns.class_(
"NukiLockUnpairAction", automation.Action
Expand Down Expand Up @@ -377,12 +378,12 @@ def _validate(config):
entity_category=ENTITY_CATEGORY_CONFIG,
icon="mdi:battery-check",
),
#cv.Optional(CONF_SLOW_SPEED_DURING_NIGHT_MODE_ENABLED_SWITCH): switch.switch_schema(
# NukiLockSlowSpeedDuringNightModeEnabledSwitch,
# device_class=DEVICE_CLASS_SWITCH,
# entity_category=ENTITY_CATEGORY_CONFIG,
# icon="mdi:speedometer-slow",
#),
cv.Optional(CONF_SLOW_SPEED_DURING_NIGHT_MODE_ENABLED_SWITCH): switch.switch_schema(
NukiLockSlowSpeedDuringNightModeEnabledSwitch,
device_class=DEVICE_CLASS_SWITCH,
entity_category=ENTITY_CATEGORY_CONFIG,
icon="mdi:speedometer-slow",
),
cv.Optional(CONF_LED_BRIGHTNESS_NUMBER): number.number_schema(
NukiLockLedBrightnessNumber,
entity_category=ENTITY_CATEGORY_CONFIG,
Expand Down Expand Up @@ -438,16 +439,17 @@ def _validate(config):
entity_category=ENTITY_CATEGORY_CONFIG,
icon="mdi:battery",
),
#cv.Optional(CONF_MOTOR_SPEED_SELECT): select.select_schema(
# NukiLockMotorSpeedSelect,
# entity_category=ENTITY_CATEGORY_CONFIG,
# icon="mdi:speedometer-medium",
#),
cv.Optional(CONF_MOTOR_SPEED_SELECT): select.select_schema(
NukiLockMotorSpeedSelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon="mdi:speedometer-medium",
),
cv.Optional(CONF_ULTRA_PAIRING_MODE, default="false"): cv.boolean,
cv.Optional(CONF_ALT_CONNECT_MODE, default="true"): cv.boolean,
cv.Optional(CONF_PAIRING_AS_APP, default="false"): cv.boolean,
cv.Optional(CONF_PAIRING_MODE_TIMEOUT, default="300s"): cv.positive_time_period_seconds,
cv.Optional(CONF_EVENT, default="nuki"): cv.string,
cv.Optional(CONF_SECURITY_PIN): cv.uint16_t,
cv.Optional(CONF_SECURITY_PIN): cv.uint32_t,
cv.Optional(CONF_QUERY_INTERVAL_CONFIG, default="3600s"): cv.positive_time_period_seconds,
cv.Optional(CONF_QUERY_INTERVAL_AUTH_DATA, default="3600s"): cv.positive_time_period_seconds,
cv.Optional(CONF_ON_PAIRING_MODE_ON): automation.validate_automation(
Expand Down Expand Up @@ -490,8 +492,11 @@ async def to_code(config):
if CONF_PAIRING_AS_APP in config:
cg.add(var.set_pairing_as_app(config[CONF_PAIRING_AS_APP]))

if config[CONF_ALT_CONNECT_MODE]:
cg.add_define("NUKI_ALT_CONNECT")
if config[CONF_ALT_CONNECT_MODE]:
cg.add_define("NUKI_ALT_CONNECT")

if CONF_ULTRA_PAIRING_MODE in config:
cg.add(var.set_ultra_pairing_mode(config[CONF_ULTRA_PAIRING_MODE]))

if CONF_ALT_CONNECT_MODE in config:
cg.add(var.set_alt_connect_mode(config[CONF_ALT_CONNECT_MODE]))
Expand Down Expand Up @@ -653,10 +658,10 @@ async def to_code(config):
await cg.register_parented(s, config[CONF_ID])
cg.add(var.set_auto_battery_type_detection_enabled_switch(s))

#if slow_speed_during_night_mode := config.get(CONF_SLOW_SPEED_DURING_NIGHT_MODE_ENABLED_SWITCH):
# s = await switch.new_switch(slow_speed_during_night_mode)
# await cg.register_parented(s, config[CONF_ID])
# cg.add(var.set_slow_speed_during_night_mode_enabled_switch(s))
if slow_speed_during_night_mode := config.get(CONF_SLOW_SPEED_DURING_NIGHT_MODE_ENABLED_SWITCH):
s = await switch.new_switch(slow_speed_during_night_mode)
await cg.register_parented(s, config[CONF_ID])
cg.add(var.set_slow_speed_during_night_mode_enabled_switch(s))

# Select
if single_button_press_action := config.get(CONF_SINGLE_BUTTON_PRESS_ACTION_SELECT):
Expand Down Expand Up @@ -723,13 +728,13 @@ async def to_code(config):
await cg.register_parented(sel, config[CONF_ID])
cg.add(var.set_battery_type_select(sel))

#if motor_speed := config.get(CONF_MOTOR_SPEED_SELECT):
# sel = await select.new_select(
# motor_speed,
# options=[CONF_MOTOR_SPEED_SELECT_OPTIONS],
# )
# await cg.register_parented(sel, config[CONF_ID])
# cg.add(var.set_motor_speed_select(sel))
if motor_speed := config.get(CONF_MOTOR_SPEED_SELECT):
sel = await select.new_select(
motor_speed,
options=[CONF_MOTOR_SPEED_SELECT_OPTIONS],
)
await cg.register_parented(sel, config[CONF_ID])
cg.add(var.set_motor_speed_select(sel))


# Callback
Expand Down Expand Up @@ -887,7 +892,7 @@ async def nuki_lock_set_pairing_mode_to_code(config, action_id, template_arg, ar
NUKI_LOCK_SET_SECURITY_PIN_SCHEMA = automation.maybe_simple_id(
{
cv.GenerateID(): cv.use_id(NukiLock),
cv.Required(CONF_SET_SECURITY_PIN): cv.templatable(cv.uint16_t)
cv.Required(CONF_SET_SECURITY_PIN): cv.templatable(cv.uint32_t)
}
)

Expand All @@ -898,6 +903,6 @@ async def nuki_lock_set_pairing_mode_to_code(config, action_id, template_arg, ar
async def nuki_lock_set_security_pin_to_code(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, paren)
security_pin_template_ = await cg.templatable(config[CONF_SET_SECURITY_PIN], args, cg.uint16)
security_pin_template_ = await cg.templatable(config[CONF_SET_SECURITY_PIN], args, cg.uint32)
cg.add(var.set_security_pin(security_pin_template_))
return var
60 changes: 31 additions & 29 deletions components/nuki_lock/nuki_lock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ void NukiLockComponent::homekit_status_to_string(const int status, char* str) {
}
}

/*void NukiLockComponent::motor_speed_to_string(const NukiLock::MotorSpeed speed, char* str) {
void NukiLockComponent::motor_speed_to_string(const NukiLock::MotorSpeed speed, char* str) {
switch (speed) {
case NukiLock::MotorSpeed::Standard:
strcpy(str, "Standard");
Expand All @@ -153,9 +153,9 @@ void NukiLockComponent::homekit_status_to_string(const int status, char* str) {
strcpy(str, "undefined");
break;
}
}*/
}

/*NukiLock::MotorSpeed NukiLockComponent::motor_speed_to_enum(const char* str) {
NukiLock::MotorSpeed NukiLockComponent::motor_speed_to_enum(const char* str) {
if(strcmp(str, "Standard") == 0) {
return NukiLock::MotorSpeed::Standard;
} else if(strcmp(str, "Insane") == 0) {
Expand All @@ -164,7 +164,7 @@ void NukiLockComponent::homekit_status_to_string(const int status, char* str) {
return NukiLock::MotorSpeed::Gentle;
}
return NukiLock::MotorSpeed::Standard;
}*/
}

uint8_t NukiLockComponent::fob_action_to_int(const char *str) {
if(strcmp(str, "No Action") == 0) {
Expand Down Expand Up @@ -703,8 +703,8 @@ void NukiLockComponent::update_config() {
ESP_LOGD(TAG, "Firmware: %i.%i.%i", config.firmwareVersion[0], config.firmwareVersion[1], config.firmwareVersion[2]);
ESP_LOGD(TAG, "Hardware: %i.%i", config.hardwareRevision[0], config.hardwareRevision[1]);

//ESP_LOGD(TAG, "Has Wifi: %s", YESNO(config.capabilities == 255 ? 0 : config.capabilities & 1));
//ESP_LOGD(TAG, "Has Thread: %s", YESNO(config.capabilities == 255 ? 0 : ((config.capabilities & 2) != 0 ? 1 : 0)));
ESP_LOGD(TAG, "Has Wifi: %s", YESNO(config.capabilities == 255 ? 0 : config.capabilities & 1));
ESP_LOGD(TAG, "Has Thread: %s", YESNO(config.capabilities == 255 ? 0 : ((config.capabilities & 2) != 0 ? 1 : 0)));
ESP_LOGD(TAG, "Matter Status: %i", (config.matterStatus == 255 ? 0 : config.matterStatus));
memset(str, 0, sizeof(str));
this->homekit_status_to_string(config.homeKitStatus, str);
Expand Down Expand Up @@ -793,14 +793,14 @@ void NukiLockComponent::update_advanced_config() {
}

// Gen 1-4 only
if (!this->is_ultra && this->auto_battery_type_detection_enabled_switch_ != nullptr) {
if (!this->ultra_pairing_mode_ && this->auto_battery_type_detection_enabled_switch_ != nullptr) {
this->auto_battery_type_detection_enabled_switch_->publish_state(advanced_config.automaticBatteryTypeDetection);
}

// Ultra only
/*if (this->is_ultra && this->slow_speed_during_night_mode_enabled_switch_ != nullptr) {
if (this->ultra_pairing_mode_ && this->slow_speed_during_night_mode_enabled_switch_ != nullptr) {
this->slow_speed_during_night_mode_enabled_switch_->publish_state(advanced_config.enableSlowSpeedDuringNightMode);
}*/
}
#endif

#ifdef USE_NUMBER
Expand All @@ -823,18 +823,18 @@ void NukiLockComponent::update_advanced_config() {
}

// Gen 1-4 only
if (!this->is_ultra_ && this->battery_type_select_ != nullptr) {
if (!this->ultra_pairing_mode_ && this->battery_type_select_ != nullptr) {
memset(str, 0, sizeof(str));
this->battery_type_to_string(advanced_config.batteryType, str);
this->battery_type_select_->publish_state(str);
}

// Ultra
/*if (this->is_ultra_ && this->motor_speed_select_ != nullptr) {
if (this->ultra_pairing_mode_ && this->motor_speed_select_ != nullptr) {
memset(str, 0, sizeof(str));
this->motor_speed_to_string(advanced_config.motorSpeed, str);
this->motor_speed_select_->publish_state(str);
}*/
}
#endif
} else {
ESP_LOGE(TAG, "requestAdvancedConfig has resulted in %s (%d)", str, conf_req_result);
Expand Down Expand Up @@ -1125,7 +1125,7 @@ void NukiLockComponent::use_security_pin(uint32_t security_pin) {

// Set new pin
if(this->get_pin() != this->security_pin_) {
bool result = this->is_ultra_ ? this->nuki_lock_.saveUltraPincode(this->security_pin_) : this->nuki_lock_.saveSecurityPincode(this->security_pin_);
bool result = this->ultra_pairing_mode_ ? this->nuki_lock_.saveUltraPincode(this->security_pin_) : this->nuki_lock_.saveSecurityPincode(this->security_pin_);
if (result) {
ESP_LOGI(TAG, "Succesfully set security pin!");
} else {
Expand All @@ -1141,7 +1141,7 @@ bool NukiLockComponent::is_pin_valid() {
}

uint32_t NukiLockComponent::get_pin() {
if(this->is_ultra_) {
if(this->ultra_pairing_mode_) {
return this->nuki_lock_.getUltraPincode();
} else {
return this->nuki_lock_.getSecurityPincode();
Expand Down Expand Up @@ -1632,6 +1632,7 @@ void NukiLockComponent::dump_config() {
LOG_SWITCH(TAG, "Automatic Updates", this->auto_update_enabled_switch_);
LOG_SWITCH(TAG, "Single Lock Enabled", this->single_lock_enabled_switch_);
LOG_SWITCH(TAG, "DST Mode Enabled", this->dst_mode_enabled_switch_);
LOG_SWITCH(TAG, "Slow Speed During Night Mode Enabled", this->slow_speed_during_night_mode_enabled_switch_);
#endif
#ifdef USE_NUMBER
LOG_NUMBER(TAG, "LED Brightness", this->led_brightness_number_);
Expand All @@ -1647,6 +1648,7 @@ void NukiLockComponent::dump_config() {
LOG_SELECT(TAG, "Timezone", this->timezone_select_);
LOG_SELECT(TAG, "Advertising Mode", this->advertising_mode_select_);
LOG_SELECT(TAG, "Battery Type", this->battery_type_select_);
LOG_SELECT(TAG, "Motor Speed", this->motor_speed_select_);
#endif
}

Expand Down Expand Up @@ -1756,15 +1758,15 @@ void NukiLockComponent::set_config_select(const char* config, const char* value)
} else if (strcmp(config, "advertising_mode") == 0) {
Nuki::AdvertisingMode mode = this->advertising_mode_to_enum(value);
cmd_result = this->nuki_lock_.setAdvertisingMode(mode);
} else if (!this->is_ultra && strcmp(config, "battery_type") == 0) {
} else if (!this->ultra_pairing_mode_ && strcmp(config, "battery_type") == 0) {
Nuki::BatteryType type = this->battery_type_to_enum(value);
cmd_result = this->nuki_lock_.setBatteryType(type);
is_advanced = true;
}/*else if (this->is_ultra && strcmp(config, "motor_speed") == 0) {
Nuki::MotorSpeed speed = this->motor_speed_to_enum(value);
}else if (this->ultra_pairing_mode_ && strcmp(config, "motor_speed") == 0) {
NukiLock::MotorSpeed speed = this->motor_speed_to_enum(value);
cmd_result = this->nuki_lock_.setMotorSpeed(speed);
is_advanced = true;
}*/
}

if (cmd_result == Nuki::CmdResult::Success) {
if (strcmp(config, "single_button_press_action") == 0 && this->single_button_press_action_select_ != nullptr) {
Expand All @@ -1783,9 +1785,9 @@ void NukiLockComponent::set_config_select(const char* config, const char* value)
this->advertising_mode_select_->publish_state(value);
} else if (strcmp(config, "battery_type") == 0 && this->battery_type_select_ != nullptr) {
this->battery_type_select_->publish_state(value);
}/*else if (strcmp(config, "motor_speed") == 0 && this->motor_speed_select_ != nullptr) {
}else if (strcmp(config, "motor_speed") == 0 && this->motor_speed_select_ != nullptr) {
this->motor_speed_select_->publish_state(value);
}*/
}

this->config_update_ = !is_advanced;
this->advanced_config_update_ = is_advanced;
Expand Down Expand Up @@ -1836,11 +1838,11 @@ void NukiLockComponent::set_config_switch(const char* config, bool value) {
cmd_result = this->nuki_lock_.enableSingleLock(value);
} else if (strcmp(config, "dst_mode_enabled") == 0) {
cmd_result = this->nuki_lock_.enableDst(value);
} else if (!this->is_ultra && strcmp(config, "auto_battery_type_detection_enabled") == 0) {
} else if (!this->ultra_pairing_mode_ && strcmp(config, "auto_battery_type_detection_enabled") == 0) {
cmd_result = this->nuki_lock_.enableAutoBatteryTypeDetection(value);
}/*else if (this->is_ultra && strcmp(config, "slow_speed_during_night_mode_enabled") == 0) {
} else if (this->ultra_pairing_mode_ && strcmp(config, "slow_speed_during_night_mode_enabled") == 0) {
cmd_result = this->nuki_lock_.enableSlowSpeedDuringNightMode(value);
}*/
}

if (cmd_result == Nuki::CmdResult::Success)
{
Expand Down Expand Up @@ -1872,9 +1874,9 @@ void NukiLockComponent::set_config_switch(const char* config, bool value) {
this->dst_mode_enabled_switch_->publish_state(value);
} else if (strcmp(config, "auto_battery_type_detection_enabled") == 0 && this->auto_battery_type_detection_enabled_switch_ != nullptr) {
this->auto_battery_type_detection_enabled_switch_->publish_state(value);
}/*else if (strcmp(config, "slow_speed_during_night_mode_enabled") == 0 && this->slow_speed_during_night_mode_enabled_switch_ != nullptr) {
} else if (strcmp(config, "slow_speed_during_night_mode_enabled") == 0 && this->slow_speed_during_night_mode_enabled_switch_ != nullptr) {
this->slow_speed_during_night_mode_enabled_switch_->publish_state(value);
}*/
}

this->config_update_ = !is_advanced;
this->advanced_config_update_ = is_advanced;
Expand Down Expand Up @@ -1958,9 +1960,9 @@ void NukiLockBatteryTypeSelect::control(const std::string &mode) {
this->parent_->set_config_select("battery_type", mode.c_str());
}

/*void NukiLockMotorSpeedSelect::control(const std::string &mode) {
void NukiLockMotorSpeedSelect::control(const std::string &mode) {
this->parent_->set_config_select("motor_speed", mode.c_str());
}*/
}
#endif
#ifdef USE_SWITCH
void NukiLockPairingModeSwitch::write_state(bool state) {
Expand Down Expand Up @@ -2023,9 +2025,9 @@ void NukiLockAutoBatteryTypeDetectionEnabledSwitch::write_state(bool state) {
this->parent_->set_config_switch("auto_battery_type_detection_enabled", state);
}

/*void NukiLockSlowSpeedDuringNightModeEnabledSwitch::write_state(bool state) {
void NukiLockSlowSpeedDuringNightModeEnabledSwitch::write_state(bool state) {
this->parent_->set_config_switch("slow_speed_during_night_mode_enabled", state);
}*/
}
#endif
#ifdef USE_NUMBER
void NukiLockLedBrightnessNumber::control(float value) {
Expand Down
Loading

0 comments on commit f104e0f

Please sign in to comment.