Skip to content

Support Closure device type#2875

Open
nickolas-deboom wants to merge 4 commits intomainfrom
feature/closure-device-type
Open

Support Closure device type#2875
nickolas-deboom wants to merge 4 commits intomainfrom
feature/closure-device-type

Conversation

@nickolas-deboom
Copy link
Copy Markdown
Contributor

@nickolas-deboom nickolas-deboom commented Apr 3, 2026

Check all that apply

Type of Change

  • WWST Certification Request
    • If this is your first time contributing code:
      • I have reviewed the README.md file
      • I have reviewed the CODE_OF_CONDUCT.md file
      • I have signed the CLA
    • I plan on entering a WWST Certification Request or have entered a request through the WWST Certification console at developer.smartthings.com
  • Bug fix
  • New feature
  • Refactor

Checklist

  • I have performed a self-review of my code
  • I have commented my code in hard-to-understand areas
  • I have verified my changes by testing with a device or have communicated a plan for testing
  • I am adding new behavior, such as adding a sub-driver, and have added and run new unit tests to cover the new behavior

Description of Change

Add support for the Closure device type.

Note that these changes were originally in #2751, but that PR was based on a branch that would migrate the matter-window-covering driver to matter-switch, which might be done at some point but is a much larger scope. In the interest of supporting this device type sooner, this PR implements this code in matter-window-covering.

Summary of Completed Tests

Tested with VDA Closure and CHIP example app.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 3, 2026

Duplicate profile check: Warning - duplicate profiles detected.
door.yml == gate.yml

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 3, 2026

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 3, 2026

Test Results

   72 files    509 suites   0s ⏱️
2 839 tests 2 839 ✅ 0 💤 0 ❌
4 707 runs  4 707 ✅ 0 💤 0 ❌

Results for commit 68d4763.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 3, 2026

File Coverage
All files 78%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureControl/types/OverallCurrentStateStruct.lua 92%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureControl/types/MainStateEnum.lua 71%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureControl/types/Feature.lua 50%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureControl/types/OverallTargetStateStruct.lua 91%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureControl/types/CurrentPositionEnum.lua 72%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureControl/server/attributes/OverallCurrentState.lua 78%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureControl/server/attributes/OverallTargetState.lua 78%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureControl/server/attributes/MainState.lua 78%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureDimension/server/attributes/CurrentState.lua 78%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/sub_drivers/closure/closure_utils/utils.lua 88%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureDimension/types/DimensionStateStruct.lua 91%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureDimension/types/Feature.lua 50%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureControl/server/commands/MoveTo.lua 67%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureControl/server/commands/Stop.lua 48%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureControl/init.lua 71%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/lazy_load_subdriver.lua 57%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/init.lua 90%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/sub_drivers/matter-window-covering-position-updates-while-moving/can_handle.lua 70%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureDimension/init.lua 73%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/sub_drivers/closure/closure_handlers/capability_handlers.lua 77%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/sub_drivers/closure/closure_handlers/attribute_handlers.lua 90%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/embedded_clusters/ClosureDimension/server/commands/SetTarget.lua 67%
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/matter-window-covering/src/sub_drivers/closure/init.lua 81%

Minimum allowed coverage is 90%

Generated by 🐒 cobertura-action against 68d4763

@nickolas-deboom nickolas-deboom force-pushed the feature/closure-device-type branch 2 times, most recently from 611fc50 to 7a0bf8b Compare April 15, 2026 19:15
@nickolas-deboom nickolas-deboom force-pushed the feature/closure-device-type branch 3 times, most recently from b497ce6 to 3e00e9d Compare April 20, 2026 18:03
@nickolas-deboom nickolas-deboom force-pushed the feature/closure-device-type branch from 542367b to 44c80b1 Compare April 29, 2026 19:30
@hcarter-775
Copy link
Copy Markdown
Contributor

@nickolas-deboom would it make more sense to implement this closure logic as a subdriver? That way, we would overwrite the capability handlers rather than add a bunch of else's to the handlers

@nickolas-deboom nickolas-deboom force-pushed the feature/closure-device-type branch from 44c80b1 to 50c21ea Compare April 30, 2026 20:40
@nickolas-deboom
Copy link
Copy Markdown
Contributor Author

@nickolas-deboom would it make more sense to implement this closure logic as a subdriver? That way, we would overwrite the capability handlers rather than add a bunch of else's to the handlers

I think that might be a good idea

@nickolas-deboom nickolas-deboom force-pushed the feature/closure-device-type branch 2 times, most recently from 494dd19 to f33d782 Compare May 5, 2026 20:45
@nickolas-deboom nickolas-deboom force-pushed the feature/closure-device-type branch from 4b6eba2 to 84e38ff Compare May 7, 2026 18:12
local MatterDriver = require "st.matter.driver"
local version = require "version"

-- TODO: change this to < 20 once the lua libs have been updated for hub-core 61
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make a ticket to track this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wasn't a permanent todo as this is already done as of 61.2 so I will update this in a commit within this PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in 68d4763

optional: true
categories:
- name: Blind
- id: windowShade4
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are there multiple components in each of these profiles, and why are there 4 in each? Is 4 an arbitrarily selection?

Copy link
Copy Markdown
Contributor Author

@nickolas-deboom nickolas-deboom May 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, 4 is arbitrary since i wasn't sure how many closure panels to typically expect (the spec just says 0+). The example devices I've seen so far have only had up to 2 so I think 4 should be good however I will define this as a constant as you suggested in another comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify, a closure consists of 1 endpoint implementing the ClosureControl cluster and then any number of endpoints of the Closure Panel device type that each implement the ClosureDimension cluster. So the number of components in these profiles that are used would reflect the number of ClosureDimension endpoints.

clusters.ClosureDimension = require "embedded_clusters.ClosureDimension"
end

local mock_device = test.mock_device.build_test_matter_device(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These test cases only cover the covering type - could we add some coverage for the door/garage/gate types as well? I know that currently we would expect these to generally behave the same since the attribute handler just switches between windowShade and doorControl when checking what the device supports here, but I think it'd be good to at least have a couple door-specific unit tests to make sure this parity is maintained.

for _, ep in ipairs(eps) do
if ep ~= 0 then
table.insert(result, ep)
if #result >= 4 then break end
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure where this 4 value comes from - could you define it as a constant somewhere for documentation purposes?

-- Single ClosureDimension: enable the capability on the main component.
local found_main = false
for _, entry in ipairs(optional_caps) do
if entry[1] == "main" then
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this might be cleaner to do something like this where you define a main_component_capabilities table earlier in the function and then insert it into the table at the end, that way you can just consistently add to the main capabilities without needing to find them within this optional caps struct. You can just define main_component_capabilities up on line 143 and then insert into it directly for the battery capability checking in line 144-148, and then insert directly in this handling as well.

Then at the end of the function, just push the main_component_capabilities into the optional_caps if it is not null.

if attr.value == 0x0C then
match_profile(device, battery_support.BATTERY_PERCENTAGE)
if is_closure then
device:set_field(CLOSURE_BATTERY_SUPPORT, battery_support.BATTERY_PERCENTAGE, {persist = true})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we just pass the battery support value in the match_profile_for_closure function, like what is done for the match_profile function?

Furthermore, could we have the match_profile function itself handle both closures and other types? You could just add a line at the top of the match_profile function that calls match_profile_for_closure if the device has a ClosureControl ep. It would essentially just be centralizing the logic in this function to the match_profile function itself, which I think would be a little cleaner.

@nickolas-deboom
Copy link
Copy Markdown
Contributor Author

@hcarter-775 I made an update to move the closure handling to a subdriver in 541b896. Lemmeknow how that looks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants