Skip to content

Commit

Permalink
Merge pull request #69 from uriyacovy/fix/lock-action-freeze
Browse files Browse the repository at this point in the history
Refactor Event Logs, Security Pin as property
  • Loading branch information
uriyacovy authored Jan 19, 2025
2 parents 2c789eb + 8653afd commit aa8de94
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 172 deletions.
3 changes: 1 addition & 2 deletions .github/test-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ lock:

led_brightness:
name: "Nuki LED Brightness"
security_pin:
name: "Nuki Security Pin"
timezone_offset:
name: "Nuki Timezone: Offset"

Expand All @@ -101,6 +99,7 @@ lock:

pairing_mode_timeout: 300s
event: "nuki"
security_pin: 1234

on_pairing_mode_on_action:
- lambda: ESP_LOGI("nuki_lock", "Pairing mode turned on");
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Compile Firmware
uses: esphome/build-action@v4.0.1
uses: esphome/build-action@v5.0.0
with:
yaml-file: .github/test-config.yaml
32 changes: 26 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ lock:
# Optional: Settings
pairing_mode_timeout: 300s
event: "nuki"
security_pin: 1234
# Optional: Binary Sensors
is_connected:
name: "Nuki Connected"
Expand Down Expand Up @@ -59,8 +60,6 @@ lock:
led_enabled:
name: "Nuki LED Signal"
# Optional: Number Inputs
security_pin:
name: "Nuki Security Pin"
led_brightness:
name: "Nuki LED Brightness"
timezone_offset:
Expand Down Expand Up @@ -197,6 +196,19 @@ on_...:
- nuki_lock.unpair:
```

### Action: Security Pin

> [!IMPORTANT]
> Overriding the security PIN will save it to flash!
> To revert back to the PIN defined in your YAML configuration, you must set the override PIN to `0`.

To override the security pin without recompiling, use the following action:
```yaml
on_...:
- nuki_lock.set_security_pin:
security_pin: 1234
```

### Callbacks
To run specific actions when certain events occur, you can use the following callbacks:
```yaml
Expand All @@ -209,14 +221,18 @@ on_paired_action:
```

### Events
By default, this component sends Nuki logs as events to Home Assistant, enabling you to use them in automations.
By default, this component sends Nuki logs as events to Home Assistant, enabling you to use them in automations.

> [!IMPORTANT]
> To receive events, **you must set your security PIN**.
> Without it, it's not possible to access any event logs from your lock.

- **To Disable Logs**: Set the `event` property in your YAML configuration to `none` if you don't want to receive log events.

- **To View Log Events**: Go to **Home Assistant Developer Tools** -> **Events**, and listen for `esphome.nuki` events to monitor log activity.

These log events provide insights into lock operations and help fine-tune automations based on real-time lock data.

These log events provide insights into lock operations and help fine-tune automations based on lock data.
Keep in mind that the logs **are not displayed in real-time** and may take up to a minute to arrive.

Example Event:
```yaml
Expand Down Expand Up @@ -246,6 +262,11 @@ context:

## Entities

> [!IMPORTANT]
> Most settings entities **require the security PIN** to make changes.
> Without the PIN, modifying these settings is not possible.
> Additionally, the `Last Unlock User` feature will only function if events are enabled!

**Lock:**
- Lock

Expand Down Expand Up @@ -291,7 +312,6 @@ context:
**Number Input:**
- LED Brightness
- Timezone Offset
- Security Pin

**Button:**
- Unpair Device
Expand Down
52 changes: 36 additions & 16 deletions components/nuki_lock/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
CONF_ADVERTISING_MODE_SELECT = "advertising_mode"

CONF_LED_BRIGHTNESS_NUMBER = "led_brightness"
CONF_SECURITY_PIN_NUMBER = "security_pin"
CONF_SECURITY_PIN = "security_pin"
CONF_TIMEZONE_OFFSET_NUMBER = "timezone_offset"

CONF_BUTTON_PRESS_ACTION_SELECT_OPTIONS = [
Expand Down Expand Up @@ -139,6 +139,7 @@
CONF_EVENT = "event"

CONF_SET_PAIRING_MODE = "pairing_mode"
CONF_SET_SECURITY_PIN = "security_pin"

CONF_ON_PAIRING_MODE_ON = "on_pairing_mode_on_action"
CONF_ON_PAIRING_MODE_OFF = "on_pairing_mode_off_action"
Expand All @@ -165,7 +166,6 @@
NukiLockDstModeEnabledSwitch = nuki_lock_ns.class_("NukiLockDstModeEnabledSwitch", switch.Switch, cg.Component)

NukiLockLedBrightnessNumber = nuki_lock_ns.class_("NukiLockLedBrightnessNumber", number.Number, cg.Component)
NukiLockSecurityPinNumber = nuki_lock_ns.class_("NukiLockSecurityPinNumber", number.Number, cg.Component)
NukiLockTimeZoneOffsetNumber = nuki_lock_ns.class_("NukiLockTimeZoneOffsetNumber", number.Number, cg.Component)

NukiLockSingleButtonPressActionSelect = nuki_lock_ns.class_("NukiLockSingleButtonPressActionSelect", select.Select, cg.Component)
Expand All @@ -184,6 +184,10 @@
"NukiLockPairingModeAction", automation.Action
)

NukiLockSecurityPinAction = nuki_lock_ns.class_(
"NukiLockSecurityPinAction", automation.Action
)

PairingModeOnTrigger = nuki_lock_ns.class_("PairingModeOnTrigger", automation.Trigger.template())
PairingModeOffTrigger = nuki_lock_ns.class_("PairingModeOffTrigger", automation.Trigger.template())
PairedTrigger = nuki_lock_ns.class_("PairedTrigger", automation.Trigger.template())
Expand Down Expand Up @@ -329,11 +333,7 @@
entity_category=ENTITY_CATEGORY_CONFIG,
icon="mdi:brightness-6",
),
cv.Optional(CONF_SECURITY_PIN_NUMBER): number.number_schema(
NukiLockSecurityPinNumber,
entity_category=ENTITY_CATEGORY_CONFIG,
icon="mdi:shield-key",
).extend({ cv.Optional(CONF_MODE, default="BOX"): cv.enum(NUMBER_MODES, upper=True), }),

cv.Optional(CONF_TIMEZONE_OFFSET_NUMBER): number.number_schema(
NukiLockTimeZoneOffsetNumber,
entity_category=ENTITY_CATEGORY_CONFIG,
Expand Down Expand Up @@ -378,6 +378,7 @@

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_ON_PAIRING_MODE_ON): automation.validate_automation(
{
Expand Down Expand Up @@ -408,6 +409,9 @@ async def to_code(config):

if CONF_EVENT in config:
cg.add(var.set_event("esphome." + config[CONF_EVENT]))

if CONF_SECURITY_PIN in config:
cg.add(var.set_security_pin(config[CONF_SECURITY_PIN]))

# Binary Sensor
if is_connected := config.get(CONF_IS_CONNECTED):
Expand Down Expand Up @@ -462,13 +466,6 @@ async def to_code(config):
await cg.register_parented(n, config[CONF_ID])
cg.add(var.set_led_brightness_number(n))

if security_pin := config.get(CONF_SECURITY_PIN_NUMBER):
n = await number.new_number(
security_pin, min_value=0, max_value=65535, step=1
)
await cg.register_parented(n, config[CONF_ID])
cg.add(var.set_security_pin_number(n))

if timezone_offset := config.get(CONF_TIMEZONE_OFFSET_NUMBER):
n = await number.new_number(
timezone_offset, min_value=-60, max_value=60, step=1
Expand Down Expand Up @@ -620,14 +617,16 @@ async def to_code(config):

# Libraries
cg.add_library("Preferences", None)
cg.add_library("h2zero/NimBLE-Arduino", "1.4.0")
cg.add_library("h2zero/NimBLE-Arduino", "1.4.2")
cg.add_library("Crc16", None)
cg.add_library(
None,
None,
"https://github.com/I-Connect/NukiBleEsp32#93e7da927171c8973b7ef857c7fa644c174ed47d",
"https://github.com/I-Connect/NukiBleEsp32#940d809",
)

cg.add_define("NUKI_ALT_CONNECT")


# Actions
NukiLockUnpairAction = nuki_lock_ns.class_(
Expand Down Expand Up @@ -666,4 +665,25 @@ async def nuki_lock_set_pairing_mode_to_code(config, action_id, template_arg, ar
var = cg.new_Pvariable(action_id, template_arg, paren)
pairing_mode_template_ = await cg.templatable(config[CONF_SET_PAIRING_MODE], args, cg.bool_)
cg.add(var.set_pairing_mode(pairing_mode_template_))
return var




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)
}
)

@automation.register_action(
"nuki_lock.set_security_pin", NukiLockSecurityPinAction, NUKI_LOCK_SET_SECURITY_PIN_SCHEMA
)

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)
cg.add(var.set_security_pin(security_pin_template_))
return var
Loading

0 comments on commit aa8de94

Please sign in to comment.