-
Notifications
You must be signed in to change notification settings - Fork 475
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
Aqara Wireless Mini Switch T1 #1145
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 |
---|---|---|
@@ -0,0 +1,108 @@ | ||
-- Copyright 2024 SmartThings | ||
-- | ||
-- Licensed under the Apache License, Version 2.0 (the "License"); | ||
-- you may not use this file except in compliance with the License. | ||
-- You may obtain a copy of the License at | ||
-- | ||
-- http://www.apache.org/licenses/LICENSE-2.0 | ||
-- | ||
-- Unless required by applicable law or agreed to in writing, software | ||
-- distributed under the License is distributed on an "AS IS" BASIS, | ||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
-- See the License for the specific language governing permissions and | ||
-- limitations under the License. | ||
|
||
local battery_defaults = require "st.zigbee.defaults.battery_defaults" | ||
local clusters = require "st.zigbee.zcl.clusters" | ||
local cluster_base = require "st.zigbee.cluster_base" | ||
local data_types = require "st.zigbee.data_types" | ||
local capabilities = require "st.capabilities" | ||
|
||
|
||
local PowerConfiguration = clusters.PowerConfiguration | ||
local PRIVATE_CLUSTER_ID = 0xFCC0 | ||
local PRIVATE_ATTRIBUTE_ID = 0x0009 | ||
local MFG_CODE = 0x115F | ||
|
||
local MULTISTATE_INPUT_CLUSTER_ID = 0x0012 | ||
local PRESENT_ATTRIBUTE_ID = 0x0055 | ||
|
||
local FINGERPRINTS = { | ||
{ mfr = "LUMI", model = "lumi.remote.b1acn02" } | ||
} | ||
|
||
local configuration = { | ||
{ | ||
cluster = MULTISTATE_INPUT_CLUSTER_ID, | ||
attribute = PRESENT_ATTRIBUTE_ID, | ||
minimum_interval = 3, | ||
maximum_interval = 7200, | ||
data_type = data_types.Uint16, | ||
reportable_change = 1 | ||
}, | ||
{ | ||
cluster = PowerConfiguration.ID, | ||
attribute = PowerConfiguration.attributes.BatteryVoltage.ID, | ||
minimum_interval = 30, | ||
maximum_interval = 3600, | ||
data_type = PowerConfiguration.attributes.BatteryVoltage.base_type, | ||
reportable_change = 1 | ||
} | ||
} | ||
|
||
local function present_value_attr_handler(driver, device, value, zb_rx) | ||
if value.value == 1 then | ||
device:emit_event(capabilities.button.button.pushed({state_change = true})) | ||
elseif value.value == 2 then | ||
device:emit_event(capabilities.button.button.double({state_change = true})) | ||
elseif value.value == 0 then | ||
device:emit_event(capabilities.button.button.held({state_change = true})) | ||
end | ||
end | ||
|
||
local is_aqara_products = function(opts, driver, device) | ||
for _, fingerprint in ipairs(FINGERPRINTS) do | ||
if device:get_manufacturer() == fingerprint.mfr and device:get_model() == fingerprint.model then | ||
return true | ||
end | ||
end | ||
return false | ||
end | ||
|
||
local function device_init(driver, device) | ||
battery_defaults.build_linear_voltage_init(2.6, 3.0)(driver, device) | ||
if configuration ~= nil then | ||
for _, attribute in ipairs(configuration) do | ||
device:add_configured_attribute(attribute) | ||
device:add_monitored_attribute(attribute) | ||
end | ||
end | ||
end | ||
|
||
local function added_handler(self, device) | ||
device:send(cluster_base.write_manufacturer_specific_attribute(device, | ||
PRIVATE_CLUSTER_ID, PRIVATE_ATTRIBUTE_ID, MFG_CODE, data_types.Uint8, 1)) | ||
device:emit_event(capabilities.button.supportedButtonValues({"pushed","held","double"}, {visibility = { displayed = false }})) | ||
device:emit_event(capabilities.button.numberOfButtons({value = 1})) | ||
device:emit_event(capabilities.button.button.pushed({state_change = false})) | ||
device:emit_event(capabilities.battery.battery(100)) | ||
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 could be missing something, but is the battery value held at 100%? Is there a specific function that is updating the value? Or is it an automatic reportable change? 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. This is the "added" lifecycle event handler that fires when the device is added for the first time. In general we do this so that the value is populated on add so there are no UI hiccups. After the fact, the value will be read using the standard zigbee attributes and handled by the defaults. |
||
end | ||
|
||
local aqara_wireless_switch_handler = { | ||
NAME = "Aqara Wireless Switch Handler", | ||
lifecycle_handlers = { | ||
init = device_init, | ||
added = added_handler | ||
}, | ||
zigbee_handlers = { | ||
attr = { | ||
[MULTISTATE_INPUT_CLUSTER_ID] = { | ||
[PRESENT_ATTRIBUTE_ID] = present_value_attr_handler | ||
} | ||
} | ||
}, | ||
can_handle = is_aqara_products | ||
} | ||
|
||
return aqara_wireless_switch_handler | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
-- Copyright 2024 SmartThings | ||
-- | ||
-- Licensed under the Apache License, Version 2.0 (the "License"); | ||
-- you may not use this file except in compliance with the License. | ||
-- You may obtain a copy of the License at | ||
-- | ||
-- http://www.apache.org/licenses/LICENSE-2.0 | ||
-- | ||
-- Unless required by applicable law or agreed to in writing, software | ||
-- distributed under the License is distributed on an "AS IS" BASIS, | ||
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
-- See the License for the specific language governing permissions and | ||
-- limitations under the License. | ||
local test = require "integration_test" | ||
local t_utils = require "integration_test.utils" | ||
local zigbee_test_utils = require "integration_test.zigbee_test_utils" | ||
local capabilities = require "st.capabilities" | ||
local clusters = require "st.zigbee.zcl.clusters" | ||
local cluster_base = require "st.zigbee.cluster_base" | ||
local data_types = require "st.zigbee.data_types" | ||
|
||
|
||
local MULTISTATE_INPUT_CLUSTER_ID = 0x0012 | ||
local PRESENT_ATTRIBUTE_ID = 0x0055 | ||
local PowerConfiguration = clusters.PowerConfiguration | ||
|
||
local MFG_CODE = 0x115F | ||
local PRIVATE_CLUSTER_ID = 0xFCC0 | ||
local PRIVATE_ATTRIBUTE_ID = 0x0009 | ||
|
||
|
||
local mock_device_t1 = test.mock_device.build_test_zigbee_device( | ||
{ | ||
profile = t_utils.get_profile_definition("one-button-battery.yml"), | ||
zigbee_endpoints = { | ||
[1] = { | ||
id = 1, | ||
manufacturer = "LUMI", | ||
model = "lumi.remote.b1acn02", | ||
server_clusters = { 0x0001, 0x0012 } | ||
} | ||
} | ||
} | ||
) | ||
|
||
zigbee_test_utils.prepare_zigbee_env_info() | ||
local function test_init() | ||
test.mock_device.add_test_device(mock_device_t1) | ||
end | ||
|
||
test.set_test_init_function(test_init) | ||
|
||
test.register_coroutine_test( | ||
"Handle added lifecycle", | ||
function() | ||
test.socket.device_lifecycle:__queue_receive({ mock_device_t1.id, "added" }) | ||
|
||
test.socket.zigbee:__expect_send({ mock_device_t1.id, | ||
cluster_base.write_manufacturer_specific_attribute(mock_device_t1, PRIVATE_CLUSTER_ID, PRIVATE_ATTRIBUTE_ID, MFG_CODE, | ||
data_types.Uint8, 1) }) | ||
|
||
|
||
test.socket.capability:__expect_send(mock_device_t1:generate_test_message("main", capabilities.button.supportedButtonValues({"pushed","held","double"}, {visibility = { displayed = false }}))) | ||
test.socket.capability:__expect_send(mock_device_t1:generate_test_message("main", capabilities.button.numberOfButtons({value = 1}))) | ||
test.socket.capability:__expect_send(mock_device_t1:generate_test_message("main", capabilities.button.button.pushed({state_change = false}))) | ||
test.socket.capability:__expect_send(mock_device_t1:generate_test_message("main", capabilities.battery.battery(100))) | ||
end | ||
) | ||
|
||
test.register_coroutine_test( | ||
"Reported button should be handled: pushed true", | ||
function() | ||
local attr_report_data = { | ||
{ PRESENT_ATTRIBUTE_ID, data_types.Uint16.ID, 0x0001 } | ||
} | ||
test.socket.zigbee:__queue_receive({ | ||
mock_device_t1.id, | ||
zigbee_test_utils.build_attribute_report(mock_device_t1, MULTISTATE_INPUT_CLUSTER_ID, attr_report_data, MFG_CODE) | ||
}) | ||
test.socket.capability:__expect_send(mock_device_t1:generate_test_message("main", | ||
capabilities.button.button.pushed({state_change = true}))) | ||
end | ||
) | ||
|
||
|
||
test.register_coroutine_test( | ||
"Reported button should be handled: double true", | ||
function() | ||
local attr_report_data = { | ||
{ PRESENT_ATTRIBUTE_ID, data_types.Uint16.ID, 0x0002 } | ||
} | ||
test.socket.zigbee:__queue_receive({ | ||
mock_device_t1.id, | ||
zigbee_test_utils.build_attribute_report(mock_device_t1, MULTISTATE_INPUT_CLUSTER_ID, attr_report_data, MFG_CODE) | ||
}) | ||
test.socket.capability:__expect_send(mock_device_t1:generate_test_message("main", | ||
capabilities.button.button.double({state_change = true}))) | ||
end | ||
) | ||
|
||
test.register_coroutine_test( | ||
"Reported button should be handled: held true", | ||
function() | ||
local attr_report_data = { | ||
{ PRESENT_ATTRIBUTE_ID, data_types.Uint16.ID, 0x0000 } | ||
} | ||
test.socket.zigbee:__queue_receive({ | ||
mock_device_t1.id, | ||
zigbee_test_utils.build_attribute_report(mock_device_t1, MULTISTATE_INPUT_CLUSTER_ID, attr_report_data, MFG_CODE) | ||
}) | ||
test.socket.capability:__expect_send(mock_device_t1:generate_test_message("main", | ||
capabilities.button.button.held({state_change = true}))) | ||
end | ||
) | ||
|
||
test.register_message_test( | ||
"Battery voltage report should be handled", | ||
{ | ||
{ | ||
channel = "zigbee", | ||
direction = "receive", | ||
message = { mock_device_t1.id, PowerConfiguration.attributes.BatteryVoltage:build_test_attr_report(mock_device_t1, 30) } | ||
}, | ||
{ | ||
channel = "capability", | ||
direction = "send", | ||
message = mock_device_t1:generate_test_message("main", capabilities.battery.battery(100)) | ||
} | ||
} | ||
) | ||
|
||
|
||
|
||
test.run_registered_tests() |
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.
Missing CopyRight Profile.