-
Notifications
You must be signed in to change notification settings - Fork 524
Support DPS feature #2750
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Support DPS feature #2750
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,6 +64,9 @@ local subscribed_attributes = { | |
| [capabilities.lock.ID] = { | ||
| DoorLock.attributes.LockState | ||
| }, | ||
| [capabilities.doorState.ID] = { | ||
| DoorLock.attributes.DoorState | ||
| }, | ||
| [capabilities.remoteControlStatus.ID] = { | ||
| DoorLock.attributes.OperatingMode | ||
| }, | ||
|
|
@@ -168,6 +171,12 @@ local function match_profile_modular(driver, device) | |
| local clus_has_feature = function(feature_bitmap) | ||
| return DoorLock.are_features_supported(feature_bitmap, ep_cluster.feature_map) | ||
| end | ||
| if clus_has_feature(DoorLock.types.Feature.DOOR_POSITION_SENSOR) then | ||
| table.insert(main_component_capabilities, capabilities.doorState.ID) | ||
| device.thread:call_with_delay(5, function(t) | ||
| device:emit_event(capabilities.doorState.supportedDoorStates({"open", "closed"}, {visibility = {displayed = false}})) -- open and closed are mandatory | ||
| end) | ||
|
Comment on lines
+229
to
+231
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should handle this in infoChanged, gated behind a profile change, since this has the possibility of failing (if a profile change does not occur in <5 seconds)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to the discussion here: #2763 |
||
| end | ||
| if clus_has_feature(DoorLock.types.Feature.USER) then | ||
| table.insert(main_component_capabilities, capabilities.lockUsers.ID) | ||
| end | ||
|
|
@@ -330,6 +339,30 @@ local function lock_state_handler(driver, device, ib, response) | |
| end) | ||
| end | ||
|
|
||
| local function door_state_handler(driver, device, ib, response) | ||
| if ib.data.value == nil then return end | ||
| local DoorStateEnum = DoorLock.types.DoorStateEnum | ||
| local doorState = capabilities.doorState.doorState | ||
| local DOOR_STATE_MAP = { | ||
| [DoorStateEnum.DOOR_OPEN] = doorState.open, | ||
| [DoorStateEnum.DOOR_CLOSED] = doorState.closed, | ||
| [DoorStateEnum.DOOR_JAMMED] = doorState.jammed, | ||
| [DoorStateEnum.DOOR_FORCED_OPEN] = doorState.forcedOpen, | ||
| [DoorStateEnum.DOOR_UNSPECIFIED_ERROR] = doorState.unspecifiedError, | ||
| [DoorStateEnum.DOOR_AJAR] = doorState.ajar | ||
| } | ||
| device:emit_event(DOOR_STATE_MAP[ib.data.value]()) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| local supportedDoorStates = device:get_latest_state("main", capabilities.doorState.ID, capabilities.doorState.supportedDoorStates.NAME) or {} | ||
| for _, state in pairs(supportedDoorStates) do | ||
| if state == DOOR_STATE_MAP[ib.data.value].NAME then | ||
| return | ||
| end | ||
| end | ||
| table.insert(supportedDoorStates, DOOR_STATE_MAP[ib.data.value].NAME); | ||
| device:emit_event(capabilities.doorState.supportedDoorStates(supportedDoorStates, {visibility = {displayed = false}})) | ||
| end | ||
|
|
||
| --------------------- | ||
| -- Operating Modes -- | ||
| --------------------- | ||
|
|
@@ -2831,6 +2864,7 @@ local new_matter_lock_handler = { | |
| attr = { | ||
| [DoorLock.ID] = { | ||
| [DoorLock.attributes.LockState.ID] = lock_state_handler, | ||
| [DoorLock.attributes.DoorState.ID] = door_state_handler, | ||
| [DoorLock.attributes.OperatingMode.ID] = operating_modes_handler, | ||
| [DoorLock.attributes.NumberOfTotalUsersSupported.ID] = total_users_supported_handler, | ||
| [DoorLock.attributes.NumberOfPINUsersSupported.ID] = pin_users_supported_handler, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know that at least some locks will set the
DOOR_POSITION_SENSORfeature flag by default even if a door sensor is not configured. They will report NULL for theDoorStateattribute until one has been configured. So I think we should checkDoorStateand theDPSflag and if they are non-NULL and the flag is set then we can saydoorStateis supported on this lock.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tpmanley
I am sorry for the late reply and thank you for the review.
Do you mean to read
DoorLockcluster'sAttributeListand set the flag if there isDoorStateattribute?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem @HunsupJung . I mean reading the DoorState attribute to confirm it's a non-null value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tpmanley
How about setting to
unspecifiedErrorwith logging whenDoorStateattribute is nil?I think It's not easy to change profile when device start sending the normal value for
DoorStateafter continuously sending nil value.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can do something similar to #2828 by setting a field like
profiling_data.DOOR_STATE_NON_NULLwhen theDoorStateattribute is reported as a non-null value. When that field changes from not being set to being set, then that will trigger the re-profile.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hcarter-775 @nickolas-deboom
Could you review it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we wouldn't include the capability by default, Hunsup is right that we'd need to do a read, which would probably be fine. However, to avoid the problem of reads failing I think we could just add
DoorStateas a subscribed attribute indevice_initwithadd_subscribed_attribute, and then if we get a non-null value reported back, then do what Tom suggested withindoor_state_handlerwith some logic like this to re-profile the device:Then within match_profile, check for the presence of the
profiling_data.DOOR_STATE_NON_NULLas the basis for includingdoorStatein the profile.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, since it's not a mandatory attribute, maybe create a new separate field rather than putting this field within
profiling_data, otherwise locks that don't support DPS would be blocked here.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is my recomendation:
Using my PR here as a blueprint,
we should update this table:
Then, in
device_init:Next, in
door_state_handler:Finally, in
do_configure, we can remove this section:and we can replace it with the following logic:
probably over by the
BATTERY_SUPPORTlogic.This ensures that whether the DOOR_POSITION_SENSOR flag is set and whether the DoorState is populated, the profiling will occur as expected. It also ensures that if the doorState capability is ever set, it will never be unset. Finally, it ensures that if the DOOR_POSITION_SENSOR is ever enabled during the device's lifetime, we will re-attempt a device profile matching (at least on driver restart).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, to ensure that any re-profiling works as expected, we should generally add gating like this for all modular capability insertions:
to ensure that if an optional capability is already supported, we continue to enable it.