Skip to content

[Aqara] Roller Shade T1S - #3292

Open
seojune79 wants to merge 3 commits into
SmartThingsCommunity:mainfrom
seojune79:Aqara-Roller-Shade-T1S
Open

seojune79 wants to merge 3 commits into
SmartThingsCommunity:mainfrom
seojune79:Aqara-Roller-Shade-T1S

Conversation

@seojune79

@seojune79 seojune79 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

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

Summary of Completed Tests

@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

zigbee-window-treatment_coverage.xml

File Coverage
All files 96% ✅
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-window-treatment/src/lazy_load_subdriver.lua 57% ❌
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-window-treatment/src/window_shade_utils.lua 91% ✅
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-window-treatment/src/sombra/init.lua 95% ✅
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-window-treatment/src/aqara/init.lua 90% ✅
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-window-treatment/src/aqara/aqara_utils.lua 95% ✅
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-window-treatment/src/yoolax/init.lua 97% ✅
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-window-treatment/src/aqara/version/can_handle.lua 83% ❌
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-window-treatment/src/aqara/curtain-driver-e1/init.lua 92% ✅
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-window-treatment/src/axis/axis_version/init.lua 97% ✅
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-window-treatment/src/hanssem/init.lua 91% ✅
/home/runner/work/SmartThingsEdgeDrivers/SmartThingsEdgeDrivers/drivers/SmartThings/zigbee-window-treatment/src/VIVIDSTORM/init.lua 93% ✅

Minimum allowed coverage is 90%

Generated by 🐒 cobertura-action against 3ce2a43

@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Test Results

   73 files    546 suites   0s ⏱️
3 334 tests 3 334 ✅ 0 💤 0 ❌
5 344 runs  5 344 ✅ 0 💤 0 ❌

Results for commit 3ce2a43.

♻️ This comment has been updated with latest results.

local function init_state_handler(driver, device, value, zb_rx)
device:set_field(INIT_STATE_REPORTED, true, { persist = true })
local state = value.value == 0x02 and initializedStateWithGuide.initializedStateWithGuide.initialized() or
initializedStateWithGuide.initializedStateWithGuide.notInitialized()

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.

nit: indent to show it is a part of the line above

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.

I've updated it.

@github-actions

Copy link
Copy Markdown

local INIT_STATE_ATTRIBUTE_ID = 0x0407
local DIRECTION_ATTRIBUTE_ID = 0x0400

local ROTATE_UP_VALUE = 0x0006

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 is 0x6 instead of 0x4 (what the base aqara roller shade driver has. Is that intentional, or should they match for a consistent experience?

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.

Yes, this is intentional. According to the manufacturer's technical guide, the T1S model requires the value to be 0x6. We have also verified this expected behavior using the physical test samples.

Comment on lines +43 to +45
local level = command.args.shadeLevel > 100 and 100 or utils.round(command.args.shadeLevel)
device:emit_event(capabilities.windowShadeLevel.shadeLevel(level))
device:send_to_component(command.component, WindowCovering.server.commands.GoToLiftPercentage(device, level))

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 is the same as aqara_utils.shade_level_cmd, which should be used instead.

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.

I will update the code to use that function.

Comment on lines +91 to +92
local level = value.value > 100 and 100 or utils.round(value.value)
device:emit_event(capabilities.windowShadeLevel.shadeLevel(level))

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 is the same as aqara_utils.emit_shade_level_event which should be used to avoid duplicated code.

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.

I will replace it with the utility function.

-- re-read whenever the shade moves while the device is still not initialized.
local function current_position_lift_percentage_handler(driver, device, value, zb_rx)
if is_not_init(device) then
device:send(cluster_base.read_manufacturer_specific_attribute(device, aqara_utils.PRIVATE_CLUSTER_ID,

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 will result in a lot of reads if the controller is not yet initialized; a single move usually results in multiple current position percent reports from the device. It seems like there could be a situation where the start/stop limits of the controller are never set by the user, and so initialization never gets set, and this always issues unnecessary reads.

Currently the driver is only reading init state from the refresh handler. Is this read needed here, or can we remove it entirely? At the very least I think we need some mechanism to reduce these reads to a single read while the controller is moving the blind and it is generating reports.

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.

Due to the nature of the roller shade, initialization (setting the limits) is mandatory, not optional.

Even if a user attempts to operate the device without initialization, level control is not supported. In this uninitialized state, the device only sends a report after the motor stops completely, so the excessive read scenario you are concerned about will rarely occur. (Since the 0%-100% range is unknown without initialization, the device does not generate intermediate position reports while moving.)

This read logic was added as a safeguard to handle edge cases where the initialization state fails to update properly. Could you please take this context into consideration and review it again?

We need to consider whether prioritizing the accurate display of the current state outweighs the minimal risk of additional traffic.

Comment on lines +133 to +135
local raw_value = reverseRollerShadeDirPrefValue
device:send(cluster_base.write_manufacturer_specific_attribute(device, aqara_utils.PRIVATE_CLUSTER_ID,
DIRECTION_ATTRIBUTE_ID, aqara_utils.MFG_CODE, data_types.Boolean, raw_value))

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.

Suggested change
local raw_value = reverseRollerShadeDirPrefValue
device:send(cluster_base.write_manufacturer_specific_attribute(device, aqara_utils.PRIVATE_CLUSTER_ID,
DIRECTION_ATTRIBUTE_ID, aqara_utils.MFG_CODE, data_types.Boolean, raw_value))
device:send(cluster_base.write_manufacturer_specific_attribute(device, aqara_utils.PRIVATE_CLUSTER_ID,
DIRECTION_ATTRIBUTE_ID, aqara_utils.MFG_CODE, data_types.Boolean, reverseRollerShadeDirPrefValue))

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.

Applied the suggested change.

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