Add econet bulldog gatelock#2998
Conversation
Adds a new Matter Edge driver for the Econet Bulldog GateLock (Vendor ID 0x1568 / Product ID 0x000A). The driver subscribes to: - DoorLock.LockState -> lock capability - DoorLock.DoorState -> contactSensor capability (reed switch via Matter) - PowerSource.BatPercentRemaining -> battery capability - GeneralDiagnostics.ActiveHardwareFaults -> tamperAlert capability (fires "tampered" when kTamperDetected is present in the list, "clear" when it is removed; firmware sets this on a 4-strike keypad brute-force trip and clears it when the lockout expires) - DoorLock.DoorLockAlarm event (legacy fallback for older firmware builds that only emit the event path) Implemented on st.matter.driver so the Matter secure session is established per device.
- Revert init.lua to drop GeneralDiagnostics.ActiveHardwareFaults subscription that crashed the driver on load - Use the generic profile filename matter-lock-contact-tamper.yml (previous gatelock-matter.yml predated the rename) - Update fingerprints.yml to reference the renamed profile - Restore README tamper-alert section to the DoorLockAlarm event path
ctowns
left a comment
There was a problem hiding this comment.
Thank you for the documentation, including testing results!
I think this functionality might be better suited as a sub driver within the existing matter-lock driver. Sub drivers allow us to provide device specific overrides to handlers as needed while still being able to inherit the same default behavior as all other devices.
Based on my review of this PR, it looks like the only unique handler for this device would be door_lock_alarm_handler, which has the device-specific TAMPER_CLEAR_DELAY_S for delaying clearing the tamper alert. However, the rest of the handlers look like they are similar to what already exists in our matter-lock driver.
Therefore, these change can be moved to a sub driver where only the device-specific behavior will need to be implemented, and the rest of the functions do not need to be defined since we can just use the existing definitions in the parent driver. Could you move these changes to a sub driver? You would only need to include the handler for the door lock alarm, and the rest of the functionality will be inherited from the parrent driver. So the sub driver would look something like this:
-- Econet GateLock Matter Edge Driver.
--
-- Built on st.matter.driver (NOT the generic st.driver) — this is the
-- Matter-specific driver class that actually attaches the secure
-- matter_channel session to each device. Using the generic Driver class
-- causes "matter_channel nil" because no Matter subsystem hookup happens.
local MatterDriver = require "st.matter.driver"
local clusters = require "st.matter.clusters"
local capabilities = require "st.capabilities"
local DoorLock = clusters.DoorLock
----------------------------------------------------------------------
-- EVENT HANDLERS
----------------------------------------------------------------------
-- Firmware locks out the keypad for ~10 s on the 4-strike brute-force trip.
-- Auto-clear after 15 s (10 s lockout + 5 s buffer) so SmartThings tracks
-- a real detected->clear transition without waiting for a driver restart.
local TAMPER_CLEAR_DELAY_S = 15
local function door_lock_alarm_handler(driver, device, ib, response)
device:emit_event(capabilities.tamperAlert.tamper.detected())
device.thread:call_with_delay(TAMPER_CLEAR_DELAY_S, function()
device:emit_event(capabilities.tamperAlert.tamper.clear())
end)
end
----------------------------------------------------------------------
-- DRIVER TABLE (passed as 2nd arg to MatterDriver)
----------------------------------------------------------------------
local matter_lock_driver = {
matter_handlers = {
event = {
[DoorLock.ID] = {
[DoorLock.events.DoorLockAlarm.ID] = door_lock_alarm_handler,
},
},
},
subscribed_attributes = {
[capabilities.lock.ID] = {
DoorLock.attributes.LockState,
},
[capabilities.contactSensor.ID] = {
DoorLock.attributes.DoorState,
},
[capabilities.battery.ID] = {
PowerSource.attributes.BatPercentRemaining,
},
},
subscribed_events = {
[capabilities.tamperAlert.ID] = {
DoorLock.events.DoorLockAlarm,
},
},
}
local matter_driver = MatterDriver("econet-gatelock", matter_lock_driver)
matter_driver:run()
Let me know if you have any questions!
| deviceProfileName: matter-lock-contact-tamper | ||
| vendorId: 0x1568 # Econet Controls Inc (5480) | ||
| productId: 0x000A # 10 (Bulldog GateLock) | ||
| deviceTypes: |
There was a problem hiding this comment.
The deviceTypes are not needed here since we are matching directly on the vendorId and productId, so they can be removed.
There was a problem hiding this comment.
Thanks @ctowns! One quick clarifying question before I refactor:
I noticed your example sub-driver includes
[capabilities.contactSensor.ID] = { DoorLock.attributes.DoorState }
in subscribed_attributes. The Bulldog GateLock exposes the standard
Matter DoorLock.DoorState attribute from a physical reed switch on
the gate frame, and I'd like to keep surfacing it as contactSensor
in the SmartThings app so users can see whether the gate is actually
open or closed (separate from the locked/unlocked).
To make sure I refactor correctly, can you confirm:
- Is the existing matter-lock parent driver expected to map
DoorState->contactSensor.contactautomatically, or should the
sub-driver include a small handler for that mapping? - Which profile should the fingerprint reference? None of the current
matter-lock profiles includecontactSensor. Should I add a new
profile (e.g.lock-user-pin-contact-tamper-battery) under
matter-lock/profiles/, or is there a preferred way to ship a
contactSensor-capable lock profile?
There was a problem hiding this comment.
Is the existing matter-lock parent driver expected to map
DoorState -> contactSensor.contact automatically, or should the
sub-driver include a small handler for that mapping?
Good question! I hadn't realized the contactSensor handling was unique to this device and I had accidentally removed it from the example above. To answer your question, we are currently working on implementing a capability specifically for handling DoorState, and that implementation would be handled in the parent driver and would not require additional implementation in the sub driver. You can see the proposed capability here! https://developer.smartthings.com/docs/devices/capabilities/proposed#doorState
Let me get back to you on the timeline, but I believe doorState may be a better fit for your use case than the contactSensor capability. Let me know if you have any questions!
Which profile should the fingerprint reference? None of the current
matter-lock profiles include contactSensor. Should I add a new
profile (e.g. lock-user-pin-contact-tamper-battery) under
matter-lock/profiles/, or is there a preferred way to ship a
contactSensor-capable lock profile?
In using the new doorState capability, we would add support for that capability to the various lock-modular profiles, which would allow for all devices (including this one) to support that capability dynamically as needed. This support would be handled by the parent driver, so you wouldn't need to implement any changes to create a new profile for use in the sub driver once the parent driver changes have landed.
So, once the doorState capability support as been added to our parent driver, I think the scope of this sub driver would be limited to the door_lock_alarm_handler functionality above that has special handling just for this device. I believe the doorState handling would be generic enough to use a generic handler in the parent driver once that is available (I will follow up on this).
Let me know if you have any questions!
Check all that apply
Type of Change
Checklist
Description of Change
New Matter Edge driver for the Econet Bulldog GateLock smart door lock
(Vendor ID 0x1568 / Product ID 0x000A, ma_doorlock device type).
Capabilities exposed:
lock— DoorLock.LockStatecontactSensor— DoorLock.DoorState (driven by the lock's reed switch)tamperAlert— GeneralDiagnostics.ActiveHardwareFaults attribute(primary, supports both detected and clear states) + DoorLock.DoorLockAlarm
event (legacy fallback for older firmware builds)
battery— PowerSource.BatPercentRemainingfirmwareUpdate,refreshWhy a custom driver:
The lock exposes its physical reed switch via the standard DoorLock.DoorState
attribute, which the stock matter-lock driver does not surface as a contact
sensor. Tamper is wired through GeneralDiagnostics so the SmartThings UI
tracks both "tampered" and "clear" states from the attribute lifecycle rather
than just an event edge.
Implemented on
st.matter.driverso the Matter secure session attaches perdevice.
Summary of Completed Tests
Tested against an Econet Bulldog GateLock running production firmware,
paired to a SmartThings hub (V3) via Matter commissioning over BLE.
app shows "Bulldog GateLock" with correct branding.
servo and the LockState attribute updates within 1 second; physical lock/
unlock from the keypad also reflects in the app.
drives the contactSensor tile open/closed in real time.
~20 s triggers the keypad's 4-strike brute-force lockout; firmware adds
kTamperDetected (10) to ActiveHardwareFaults; SmartThings tile transitions
to "tampered". When the lockout expires (~10 s), firmware removes the
fault and the tile returns to "clear".
that only emit the DoorLockAlarm event still trigger "tampered" via the
retained event handler.
attributes.
No regressions observed in 24 hours of continuous device usage.