-
Notifications
You must be signed in to change notification settings - Fork 466
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add Aqara Cube T1 Pro * Rename the profile from "aqara-cube-t1-pro" to "cube-t1-pro" * fixed thread call and removed the unused local * fixed the thread * changing folders * remove can_handle * add (1) refresh capability (2) BatteryVoltage handler (3) Testcases * remove unused variable utils
- Loading branch information
Showing
7 changed files
with
388 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
id: stse.cubeAction | ||
version: 1 | ||
status: proposed | ||
name: Cube Action | ||
ephemeral: false | ||
attributes: | ||
cubeAction: | ||
schema: | ||
type: object | ||
properties: | ||
value: | ||
title: ActionType | ||
type: string | ||
enum: | ||
- noAction | ||
- shake | ||
- rotate | ||
- pickUpAndHold | ||
- flipToSide1 | ||
- flipToSide2 | ||
- flipToSide3 | ||
- flipToSide4 | ||
- flipToSide5 | ||
- flipToSide6 | ||
additionalProperties: false | ||
required: | ||
- value | ||
enumCommands: [] | ||
commands: {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
id: stse.cubeFace | ||
version: 1 | ||
status: proposed | ||
name: Cube Face | ||
ephemeral: false | ||
attributes: | ||
cubeFace: | ||
schema: | ||
type: object | ||
properties: | ||
value: | ||
title: CubeFace | ||
type: string | ||
enum: | ||
- face1Up | ||
- face2Up | ||
- face3Up | ||
- face4Up | ||
- face5Up | ||
- face6Up | ||
additionalProperties: false | ||
required: | ||
- value | ||
enumCommands: [] | ||
commands: {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
name: 'Aqara Cube' | ||
packageKey: 'aqara-cube' | ||
permissions: | ||
zigbee: {} | ||
description: "SmartThings driver for Aqara Cube devices" | ||
vendorSupportInformation: "https://www.aqara.com/en/support/" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
zigbeeManufacturer: | ||
- id: "Lumi/lumi.remote.cagl02" | ||
deviceLabel: Aqara Cube T1 Pro | ||
manufacturer: LUMI | ||
model: lumi.remote.cagl02 | ||
deviceProfileName: cube-t1-pro |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
name: cube-t1-pro | ||
components: | ||
- id: main | ||
capabilities: | ||
- id: stse.cubeAction | ||
version: 1 | ||
- id: stse.cubeFace | ||
version: 1 | ||
- id: battery | ||
version: 1 | ||
- id: firmwareUpdate | ||
version: 1 | ||
- id: refresh | ||
version: 1 | ||
categories: | ||
- name: RemoteController | ||
metadata: | ||
mnmn: SolutionsEngineering | ||
vid: SmartThings-smartthings-Aqara_CubeT1Pro |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
local ZigbeeDriver = require "st.zigbee" | ||
local capabilities = require "st.capabilities" | ||
local data_types = require "st.zigbee.data_types" | ||
local cluster_base = require "st.zigbee.cluster_base" | ||
local battery_defaults = require "st.zigbee.defaults.battery_defaults" | ||
local clusters = require "st.zigbee.zcl.clusters" | ||
local PowerConfiguration = clusters.PowerConfiguration | ||
|
||
local PRI_CLU = 0xFCC0 | ||
local PRI_ATTR = 0x0009 | ||
local MFG_CODE = 0x115F | ||
|
||
local ROTATE_CLU = 0x000C | ||
local EVENT_CLU = 0x0012 | ||
local FACE_ATTR = 0x0149 | ||
local ACTION_ATTR = 0x0055 | ||
local CUBE_MODE = 0x0148 | ||
|
||
local cubeAction = capabilities["stse.cubeAction"] | ||
local cubeFace = capabilities["stse.cubeFace"] | ||
local cubeFaceVal = { "face1Up", "face2Up", "face3Up", "face4Up", "face5Up", "face6Up" } | ||
local cubeFlipToSideVal = { "flipToSide1", "flipToSide2", "flipToSide3", "flipToSide4", "flipToSide5", "flipToSide6" } | ||
|
||
local CUBEACTION_TIMER = "cubeAction_timer" | ||
local CUBEACTION_TIME = 3 | ||
|
||
local callback_timer = function(device) | ||
return function() | ||
device:emit_event(cubeAction.cubeAction("noAction")) | ||
end | ||
end | ||
|
||
local function reset_thread(device) | ||
local timer = device:get_field(CUBEACTION_TIMER) | ||
if timer then | ||
device.thread:cancel_timer(timer) | ||
device:set_field(CUBEACTION_TIMER, nil) | ||
end | ||
device:set_field(CUBEACTION_TIMER, device.thread:call_with_delay(CUBEACTION_TIME, callback_timer(device))) | ||
end | ||
|
||
local function data_handler(driver, device, value, zb_rx) | ||
local val = value.value | ||
if val == 0x0000 then -- Shake | ||
reset_thread(device) | ||
device:emit_event(cubeAction.cubeAction("shake")) | ||
elseif val == 0x0004 then -- hold | ||
reset_thread(device) | ||
device:emit_event(cubeAction.cubeAction("pickUpAndHold")) | ||
elseif val & 0x0400 == 0x0400 then -- Flip to side | ||
local faceNum = val & 0x0007 | ||
reset_thread(device) | ||
device:emit_event(cubeAction.cubeAction(cubeFlipToSideVal[faceNum + 0x1])) | ||
end | ||
end | ||
|
||
local function rotate_handler(driver, device, value, zb_rx) | ||
-- Rotation | ||
reset_thread(device) | ||
device:emit_event(cubeAction.cubeAction("rotate")) | ||
end | ||
|
||
local function face_handler(driver, device, value, zb_rx) | ||
local faceNum = value.value | ||
device:emit_event(cubeFace.cubeFace(cubeFaceVal[faceNum + 1])) | ||
end | ||
|
||
local function do_refresh(driver, device) | ||
-- refresh | ||
device:send(PowerConfiguration.attributes.BatteryVoltage:read(device)) | ||
end | ||
|
||
local function device_init(driver, device) | ||
local power_configuration = { | ||
cluster = PowerConfiguration.ID, | ||
attribute = PowerConfiguration.attributes.BatteryVoltage.ID, | ||
minimum_interval = 30, | ||
maximum_interval = 3600, | ||
data_type = PowerConfiguration.attributes.BatteryVoltage.base_type, | ||
reportable_change = 1 | ||
} | ||
|
||
battery_defaults.build_linear_voltage_init(2.6, 3.0)(driver, device) | ||
|
||
device:add_configured_attribute(power_configuration) | ||
device:add_monitored_attribute(power_configuration) | ||
end | ||
|
||
local function device_added(self, device) | ||
-- Set private attribute | ||
device:send(cluster_base.write_manufacturer_specific_attribute(device, | ||
PRI_CLU, PRI_ATTR, MFG_CODE, data_types.Uint8, 1)) | ||
|
||
device:send(cluster_base.write_manufacturer_specific_attribute(device, | ||
PRI_CLU, CUBE_MODE, MFG_CODE, data_types.Uint8, 1)) | ||
device:emit_event(cubeAction.cubeAction("noAction")) | ||
device:emit_event(cubeFace.cubeFace("face1Up")) | ||
do_refresh(self, device) | ||
end | ||
|
||
-- [[ register ]] | ||
local aqara_cube_t1_pro_handler = { | ||
NAME = "Aqara Cube T1 Pro", | ||
capability_handlers = { | ||
[capabilities.refresh.ID] = { | ||
[capabilities.refresh.commands.refresh.NAME] = do_refresh | ||
} | ||
}, | ||
zigbee_handlers = { | ||
attr = { | ||
[EVENT_CLU] = { | ||
[ACTION_ATTR] = data_handler | ||
}, | ||
[ROTATE_CLU] = { | ||
[ACTION_ATTR] = rotate_handler, | ||
}, | ||
[PRI_CLU] = { | ||
[FACE_ATTR] = face_handler | ||
}, | ||
[PowerConfiguration.ID] = { | ||
[PowerConfiguration.attributes.BatteryVoltage.ID] = battery_defaults.battery_volt_attr_handler | ||
} | ||
} | ||
}, | ||
lifecycle_handlers = { | ||
init = device_init, | ||
added = device_added | ||
} | ||
} | ||
|
||
local aqara_cube_t1_pro_driver = ZigbeeDriver("aqara_cube_t1_pro", aqara_cube_t1_pro_handler) | ||
aqara_cube_t1_pro_driver:run() | ||
|
170 changes: 170 additions & 0 deletions
170
drivers/Aqara/aqara-cube/src/test/test_aqara_cube_t1_pro.lua
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
local test = require "integration_test" | ||
local cluster_base = require "st.zigbee.cluster_base" | ||
local t_utils = require "integration_test.utils" | ||
local zigbee_test_utils = require "integration_test.zigbee_test_utils" | ||
local capabilities = require "st.capabilities" | ||
local data_types = require "st.zigbee.data_types" | ||
local clusters = require "st.zigbee.zcl.clusters" | ||
local PowerConfiguration = clusters.PowerConfiguration | ||
|
||
local PRI_CLU = 0xFCC0 | ||
local PRI_ATTR = 0x0009 | ||
local MFG_CODE = 0x115F | ||
|
||
local ROTATE_CLU = 0x000C | ||
local EVENT_CLU = 0x0012 | ||
local FACE_ATTR = 0x0149 | ||
local ACTION_ATTR = 0x0055 | ||
local CUBE_MODE = 0x0148 | ||
|
||
local cubeAction = capabilities["stse.cubeAction"] | ||
local cubeFace = capabilities["stse.cubeFace"] | ||
test.add_package_capability("cubeAction.yaml") | ||
test.add_package_capability("cubeFace.yaml") | ||
|
||
local CUBEACTION_TIME = 3 | ||
|
||
|
||
local mock_device = test.mock_device.build_test_zigbee_device( | ||
{ | ||
profile = t_utils.get_profile_definition("cube-t1-pro.yml"), | ||
zigbee_endpoints = { | ||
[1] = { | ||
id = 1, | ||
manufacturer = "LUMI", | ||
model = "lumi.remote.cagl02", | ||
server_clusters = { PRI_CLU } | ||
} | ||
} | ||
} | ||
) | ||
|
||
zigbee_test_utils.prepare_zigbee_env_info() | ||
|
||
local function test_init() | ||
test.mock_device.add_test_device(mock_device) | ||
end | ||
|
||
test.set_test_init_function(test_init) | ||
|
||
test.register_coroutine_test( | ||
"lifecycle - added test", | ||
function() | ||
test.socket.zigbee:__set_channel_ordering("relaxed") | ||
test.socket.capability:__set_channel_ordering("relaxed") | ||
test.socket.device_lifecycle:__queue_receive({ mock_device.id, "added" }) | ||
-- private protocol enable | ||
test.socket.zigbee:__expect_send({ mock_device.id, | ||
cluster_base.write_manufacturer_specific_attribute(mock_device, PRI_CLU, PRI_ATTR, MFG_CODE, | ||
data_types.Uint8, 1) }) | ||
-- init | ||
test.socket.zigbee:__expect_send({ mock_device.id, | ||
cluster_base.write_manufacturer_specific_attribute(mock_device, PRI_CLU, CUBE_MODE, MFG_CODE, | ||
data_types.Uint8, 1) }) | ||
test.socket.capability:__expect_send(mock_device:generate_test_message("main", cubeAction.cubeAction("noAction"))) | ||
test.socket.capability:__expect_send(mock_device:generate_test_message("main", cubeFace.cubeFace("face1Up"))) | ||
test.socket.zigbee:__expect_send({ mock_device.id, PowerConfiguration.attributes.BatteryVoltage:read(mock_device) }) | ||
end | ||
) | ||
|
||
test.register_coroutine_test( | ||
"capability - refresh", | ||
function() | ||
test.socket.capability:__queue_receive({ mock_device.id, | ||
{ capability = "refresh", component = "main", command = "refresh", args = {} } }) | ||
test.socket.zigbee:__expect_send({ mock_device.id, PowerConfiguration.attributes.BatteryVoltage:read(mock_device) }) | ||
end | ||
) | ||
|
||
test.register_coroutine_test( | ||
"data_handler test - shake", | ||
function() | ||
local attr_report_data = { | ||
{ ACTION_ATTR, data_types.Uint16.ID, 0x0000 } | ||
} | ||
test.socket.zigbee:__queue_receive({ | ||
mock_device.id, | ||
zigbee_test_utils.build_attribute_report(mock_device, EVENT_CLU, attr_report_data, MFG_CODE) | ||
}) | ||
test.socket.capability:__expect_send(mock_device:generate_test_message("main", | ||
cubeAction.cubeAction("shake"))) | ||
test.timer.__create_and_queue_test_time_advance_timer(CUBEACTION_TIME, "oneshot") | ||
test.mock_time.advance_time(CUBEACTION_TIME) | ||
test.socket.capability:__expect_send(mock_device:generate_test_message("main", | ||
cubeAction.cubeAction("noAction"))) | ||
end | ||
) | ||
|
||
test.register_coroutine_test( | ||
"data_handler test - pick up and hold", | ||
function() | ||
local attr_report_data = { | ||
{ ACTION_ATTR, data_types.Uint16.ID, 0x0004 } | ||
} | ||
test.socket.zigbee:__queue_receive({ | ||
mock_device.id, | ||
zigbee_test_utils.build_attribute_report(mock_device, EVENT_CLU, attr_report_data, MFG_CODE) | ||
}) | ||
test.socket.capability:__expect_send(mock_device:generate_test_message("main", | ||
cubeAction.cubeAction("pickUpAndHold"))) | ||
test.timer.__create_and_queue_test_time_advance_timer(CUBEACTION_TIME, "oneshot") | ||
test.mock_time.advance_time(CUBEACTION_TIME) | ||
test.socket.capability:__expect_send(mock_device:generate_test_message("main", | ||
cubeAction.cubeAction("noAction"))) | ||
end | ||
) | ||
|
||
test.register_coroutine_test( | ||
"data_handler test - flip to side 6", | ||
function() | ||
local attr_report_data = { | ||
{ ACTION_ATTR, data_types.Uint16.ID, 0x0405 } | ||
} | ||
test.socket.zigbee:__queue_receive({ | ||
mock_device.id, | ||
zigbee_test_utils.build_attribute_report(mock_device, EVENT_CLU, attr_report_data, MFG_CODE) | ||
}) | ||
test.socket.capability:__expect_send(mock_device:generate_test_message("main", | ||
cubeAction.cubeAction("flipToSide6"))) | ||
test.timer.__create_and_queue_test_time_advance_timer(CUBEACTION_TIME, "oneshot") | ||
test.mock_time.advance_time(CUBEACTION_TIME) | ||
test.socket.capability:__expect_send(mock_device:generate_test_message("main", | ||
cubeAction.cubeAction("noAction"))) | ||
end | ||
) | ||
|
||
test.register_coroutine_test( | ||
"rotate_handler test - rotation", | ||
function() | ||
local attr_report_data = { | ||
{ ACTION_ATTR, data_types.Uint16.ID, 0x0000 } | ||
} | ||
test.socket.zigbee:__queue_receive({ | ||
mock_device.id, | ||
zigbee_test_utils.build_attribute_report(mock_device, ROTATE_CLU, attr_report_data, MFG_CODE) | ||
}) | ||
test.socket.capability:__expect_send(mock_device:generate_test_message("main", | ||
cubeAction.cubeAction("rotate"))) | ||
test.timer.__create_and_queue_test_time_advance_timer(CUBEACTION_TIME, "oneshot") | ||
test.mock_time.advance_time(CUBEACTION_TIME) | ||
test.socket.capability:__expect_send(mock_device:generate_test_message("main", | ||
cubeAction.cubeAction("noAction"))) | ||
end | ||
) | ||
|
||
test.register_coroutine_test( | ||
"face_handler test - face up 1", | ||
function() | ||
local attr_report_data = { | ||
{ FACE_ATTR, data_types.Uint8.ID, 0x00 } | ||
} | ||
test.socket.zigbee:__queue_receive({ | ||
mock_device.id, | ||
zigbee_test_utils.build_attribute_report(mock_device, PRI_CLU, attr_report_data, MFG_CODE) | ||
}) | ||
test.socket.capability:__expect_send(mock_device:generate_test_message("main", | ||
cubeFace.cubeFace("face1Up"))) | ||
end | ||
) | ||
|
||
test.run_registered_tests() |