Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions drivers/SmartThings/zigbee-button/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,22 @@ zigbeeManufacturer:
deviceLabel: Aqara Wireless Mini Switch T1
manufacturer: LUMI
model: lumi.remote.b1acn02
deviceProfileName: one-button-battery
deviceProfileName: one-button-batteryLevel
- id: "LUMI/lumi.remote.acn003"
deviceLabel: Aqara Wireless Remote Switch E1 (Single Rocker)
manufacturer: LUMI
model: lumi.remote.acn003
deviceProfileName: one-button-battery
deviceProfileName: one-button-batteryLevel
- id: "LUMI/lumi.remote.b186acn03"
deviceLabel: Aqara Wireless Remote Switch T1 (Single Rocker)
manufacturer: LUMI
model: lumi.remote.b186acn03
deviceProfileName: one-button-batteryLevel
- id: "LUMI/lumi.remote.b286acn03"
deviceLabel: Aqara Wireless Remote Switch T1 (Double Rocker)
manufacturer: LUMI
model: lumi.remote.b286acn03
deviceProfileName: aqara-double-buttons
- id: "HEIMAN/SOS-EM"
deviceLabel: HEIMAN Button
manufacturer: HEIMAN
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: aqara-double-buttons
components:
- id: main
capabilities:
- id: button
version: 1
- id: batteryLevel
version: 1
- id: firmwareUpdate
version: 1
- id: refresh
version: 1
Comment on lines +11 to +12
Copy link
Contributor

Choose a reason for hiding this comment

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

this profile needs to include firmwareUpdate

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay, I have added the firmwareUpdate capability.

categories:
- name: RemoteController
- id: button1
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
- id: button2
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
- id: all
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: one-button-batteryLevel
components:
- id: main
capabilities:
- id: button
version: 1
- id: batteryLevel
version: 1
- id: firmwareUpdate
version: 1
- id: refresh
version: 1
categories:
- name: Button
160 changes: 101 additions & 59 deletions drivers/SmartThings/zigbee-button/src/aqara/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,74 +29,113 @@ local MFG_CODE = 0x115F
local MULTISTATE_INPUT_CLUSTER_ID = 0x0012
local PRESENT_ATTRIBUTE_ID = 0x0055

local COMP_LIST = { "button1", "button2", "all" }
local FINGERPRINTS = {
{ mfr = "LUMI", model = "lumi.remote.b1acn02" },
{ mfr = "LUMI", model = "lumi.remote.acn003" }
["lumi.remote.b1acn02"] = { mfr = "LUMI", btn_cnt = 1 },
["lumi.remote.acn003"] = { mfr = "LUMI", btn_cnt = 1 },
["lumi.remote.b186acn03"] = { mfr = "LUMI", btn_cnt = 1 },
["lumi.remote.b286acn03"] = { mfr = "LUMI", btn_cnt = 3 }
}

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
}
{
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
local end_point = zb_rx.address_header.src_endpoint.value
local btn_evt_cnt = FINGERPRINTS[device:get_model()].btn_cnt or 1
local evt = capabilities.button.button.held({ state_change = true })
if value.value == 1 then
evt = capabilities.button.button.pushed({ state_change = true })
elseif value.value == 2 then
evt = capabilities.button.button.double({ state_change = true })
end
device:emit_event(evt)
if btn_evt_cnt > 1 then
device:emit_component_event(device.profile.components[COMP_LIST[end_point]], evt)
end
end
local function battery_level_handler(driver, device, value, zb_rx)
local voltage = value.value
local batteryLevel = "normal"
if voltage <= 25 then
batteryLevel = "critical"
elseif voltage < 28 then
batteryLevel = "warning"
end
device:emit_event(capabilities.batteryLevel.battery(batteryLevel))
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
local isAqaraProducts = false
if FINGERPRINTS[device:get_model()] and FINGERPRINTS[device:get_model()].mfr == device:get_manufacturer() then
isAqaraProducts = true
end
return isAqaraProducts
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)
end
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)
end
end
end

local function added_handler(self, device)
device:emit_event(capabilities.button.supportedButtonValues({"pushed","held","double"}, {visibility = { displayed = false }}))
device:emit_event(capabilities.button.numberOfButtons({value = 1}))
button_utils.emit_event_if_latest_state_missing(device, "main", capabilities.button, capabilities.button.button.NAME, capabilities.button.button.pushed({state_change = false}))
device:emit_event(capabilities.battery.battery(100))
local btn_evt_cnt = FINGERPRINTS[device:get_model()].btn_cnt or 1

device:emit_event(capabilities.button.supportedButtonValues({ "pushed", "held", "double" },
{ visibility = { displayed = false } }))
device:emit_event(capabilities.button.numberOfButtons({ value = 1 }))
button_utils.emit_event_if_latest_state_missing(device, "main", capabilities.button, capabilities.button.button.NAME,
capabilities.button.button.pushed({ state_change = false }))
device:emit_event(capabilities.batteryLevel.battery.normal())
device:emit_event(capabilities.batteryLevel.type("CR2032"))
device:emit_event(capabilities.batteryLevel.quantity(1))

if btn_evt_cnt > 1 then
for i = 1, btn_evt_cnt do
device:emit_component_event(device.profile.components[COMP_LIST[i]],
capabilities.button.supportedButtonValues({ "pushed", "held", "double" },
{ visibility = { displayed = false } }))
device:emit_component_event(device.profile.components[COMP_LIST[i]],
capabilities.button.numberOfButtons({ value = 1 }))
device:emit_component_event(device.profile.components[COMP_LIST[i]],
capabilities.button.button.pushed({ state_change = false }))
button_utils.emit_event_if_latest_state_missing(device, COMP_LIST[i], capabilities.button,
capabilities.button.button.NAME, capabilities.button.button.pushed({ state_change = false }))
end
end
end

local function do_configure(driver, device)
local ATTR_ID = PRIVATE_ATTRIBUTE_ID_T1
local cmd_value = 1

device:configure()
if device:get_model() == "lumi.remote.b1acn02" then
device:send(cluster_base.write_manufacturer_specific_attribute(device,
PRIVATE_CLUSTER_ID, PRIVATE_ATTRIBUTE_ID_T1, MFG_CODE, data_types.Uint8, 1))
elseif device:get_model() == "lumi.remote.acn003" then
device:send(cluster_base.write_manufacturer_specific_attribute(device,
PRIVATE_CLUSTER_ID, PRIVATE_ATTRIBUTE_ID_E1, MFG_CODE, data_types.Uint8, 2))
if device:get_model() == "lumi.remote.acn003" then
ATTR_ID = PRIVATE_ATTRIBUTE_ID_E1
cmd_value = 2
end
device:send(cluster_base.write_manufacturer_specific_attribute(device,
PRIVATE_CLUSTER_ID, ATTR_ID, MFG_CODE, data_types.Uint8, cmd_value))
-- when the wireless switch T1 accesses the network, the gateway sends
-- private attribute 0009 to make the device no longer distinguish
-- between the standard gateway and the aqara gateway.
Expand All @@ -105,20 +144,23 @@ local function do_configure(driver, device)
end

local aqara_wireless_switch_handler = {
NAME = "Aqara Wireless Switch Handler",
lifecycle_handlers = {
init = device_init,
added = added_handler,
doConfigure = do_configure
},
zigbee_handlers = {
attr = {
[MULTISTATE_INPUT_CLUSTER_ID] = {
[PRESENT_ATTRIBUTE_ID] = present_value_attr_handler
}
NAME = "Aqara Wireless Switch Handler",
lifecycle_handlers = {
init = device_init,
added = added_handler,
doConfigure = do_configure
},
zigbee_handlers = {
attr = {
[MULTISTATE_INPUT_CLUSTER_ID] = {
[PRESENT_ATTRIBUTE_ID] = present_value_attr_handler
},
[PowerConfiguration.ID] = {
[PowerConfiguration.attributes.BatteryVoltage.ID] = battery_level_handler
}
},
can_handle = is_aqara_products
}
},
can_handle = is_aqara_products
}

return aqara_wireless_switch_handler
Loading
Loading