Skip to content

Commit

Permalink
Add Aqara Climate Sensor W100 (#1843)
Browse files Browse the repository at this point in the history
* Add Aqara Climate Sensor W100

This device has a Temperature Sensor(0x0302), a Humidity Sensor(0x0307), and 3 Generic Switchs(0x000F).

* It is modified to support w100 in Matter-switch, not Matter-sensor.

* Revert "It is modified to support w100 in Matter-switch, not Matter-sensor."

This reverts commit 511f361.

* It is modified to support w100 in matter-switch, not matter-sensor.

* It is modified to support w100 in matter-switch, not matter-sensor.

* Use device:get_endpoints to delete the device's fingerprint and modify it to operate more dynamically
  • Loading branch information
DongHoon-Ryu authored Jan 23, 2025
1 parent a8db39b commit 7171fd3
Show file tree
Hide file tree
Showing 3 changed files with 654 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: 3-button-battery-temperature-humidity
components:
- id: main
capabilities:
- id: temperatureMeasurement
version: 1
- id: relativeHumidityMeasurement
version: 1
- id: battery
version: 1
- id: firmwareUpdate
version: 1
- id: refresh
version: 1
categories:
- name: TempHumiditySensor
- id: button1
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
- id: button2
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
- id: button3
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
preferences:
- preferenceId: tempOffset
explicit: true
- preferenceId: humidityOffset
explicit: true
deviceConfig:
dashboard:
states:
- component: main
capability: temperatureMeasurement
version: 1
group: main
composite: true
- component: main
capability: relativeHumidityMeasurement
version: 1
group: main
values:
- label: " {{humidity.value}} {{humidity.unit}}"
composite: true
actions: []
basicPlus: []
detailView:
- component: main
capability: temperatureMeasurement
version: 1
- component: main
capability: relativeHumidityMeasurement
version: 1
- component: main
capability: battery
version: 1
- component: main
capability: refresh
version: 1
- component: button1
capability: button
version: 1
- component: button2
capability: button
version: 1
- component: button3
capability: button
version: 1
automation:
conditions:
- component: main
capability: temperatureMeasurement
version: 1
- component: main
capability: relativeHumidityMeasurement
version: 1
- component: main
capability: battery
version: 1
- component: button1
capability: button
version: 1
- component: button2
capability: button
version: 1
- component: button3
capability: button
version: 1
actions: []
89 changes: 83 additions & 6 deletions drivers/SmartThings/matter-switch/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ local EMULATE_HELD = "__emulate_held" -- for non-MSR (MomentarySwitchRelease) de
local SUPPORTS_MULTI_PRESS = "__multi_button" -- for MSM devices (MomentarySwitchMultiPress), create an event on receipt of MultiPressComplete
local INITIAL_PRESS_ONLY = "__initial_press_only" -- for devices that support MS (MomentarySwitch), but not MSR (MomentarySwitchRelease)

local TEMP_BOUND_RECEIVED = "__temp_bound_received"
local TEMP_MIN = "__temp_min"
local TEMP_MAX = "__temp_max"

local HUE_MANUFACTURER_ID = 0x100B
local AQARA_MANUFACTURER_ID = 0x115F

Expand Down Expand Up @@ -528,7 +532,7 @@ local function initialize_switch(driver, device)
table.sort(switch_eps)
table.sort(button_eps)

local profile_name = nil
local profile_name = ""

local component_map = {}
local component_map_used = false
Expand All @@ -539,7 +543,15 @@ local function initialize_switch(driver, device)
-- that have been implemented as server. This can be removed when we have
-- support for bindings.
local num_switch_server_eps = 0
local main_endpoint = find_default_endpoint(device)
local main_endpoint
local temperature_eps = device:get_endpoints(clusters.TemperatureMeasurement.ID)
local humidity_eps = device:get_endpoints(clusters.RelativeHumidityMeasurement.ID)
if #temperature_eps > 0 and #humidity_eps > 0 then
-- In case of Aqara Climate Sensor W100, in order to sequentially set the button name to button 1, 2, 3
main_endpoint = device.MATTER_DEFAULT_ENDPOINT
else
main_endpoint = find_default_endpoint(device)
end

-- If a switch endpoint is present, it will be the main endpoint and therefore the
-- main component. If button endpoints are present, they will be added as
Expand Down Expand Up @@ -613,17 +625,21 @@ local function initialize_switch(driver, device)
battery_support = true
end
if #button_eps > 1 and tbl_contains(STATIC_BUTTON_PROFILE_SUPPORTED, #button_eps) then
if #temperature_eps > 0 and #humidity_eps > 0 then
device.log.debug("So far, it means Aqara Climate Sensor W100.")
profile_name = "-temperature-humidity"
end
if battery_support then
profile_name = string.format("%d-button-battery", #button_eps)
profile_name = string.format("%d-button-battery", #button_eps) .. profile_name
else
profile_name = string.format("%d-button", #button_eps)
profile_name = string.format("%d-button", #button_eps) .. profile_name
end
elseif not battery_support then
-- a battery-less button/remote
profile_name = "button"
end

if profile_name then
if profile_name ~= "" then
device:try_update_metadata({profile = profile_name})
device:set_field(DEFERRED_CONFIGURE, true)
device:set_field(BUTTON_DEVICE_PROFILED, true)
Expand Down Expand Up @@ -1199,6 +1215,49 @@ local function device_added(driver, device)
device_init(driver, device)
end

local function temperature_attr_handler(driver, device, ib, response)
local measured_value = ib.data.value
if measured_value ~= nil then
local temp = measured_value / 100.0
local unit = "C"
device:emit_event_for_endpoint(ib.endpoint_id, capabilities.temperatureMeasurement.temperature({value = temp, unit = unit}))
end
end

local temp_attr_handler_factory = function(minOrMax)
return function(driver, device, ib, response)
if ib.data.value == nil then
return
end
local temp = ib.data.value / 100.0
local unit = "C"
set_field_for_endpoint(device, TEMP_BOUND_RECEIVED..minOrMax, ib.endpoint_id, temp)
local min = get_field_for_endpoint(device, TEMP_BOUND_RECEIVED..TEMP_MIN, ib.endpoint_id)
local max = get_field_for_endpoint(device, TEMP_BOUND_RECEIVED..TEMP_MAX, ib.endpoint_id)
if min ~= nil and max ~= nil then
if min < max then
-- Only emit the capability for RPC version >= 5 (unit conversion for
-- temperature range capability is only supported for RPC >= 5)
if version.rpc >= 5 then
device:emit_event_for_endpoint(ib.endpoint_id, capabilities.temperatureMeasurement.temperatureRange({ value = { minimum = min, maximum = max }, unit = unit }))
end
set_field_for_endpoint(device, TEMP_BOUND_RECEIVED..TEMP_MIN, ib.endpoint_id, nil)
set_field_for_endpoint(device, TEMP_BOUND_RECEIVED..TEMP_MAX, ib.endpoint_id, nil)
else
device.log.warn_with({hub_logs = true}, string.format("Device reported a min temperature %d that is not lower than the reported max temperature %d", min, max))
end
end
end
end

local function humidity_attr_handler(driver, device, ib, response)
local measured_value = ib.data.value
if measured_value ~= nil then
local humidity = utils.round(measured_value / 100.0)
device:emit_event_for_endpoint(ib.endpoint_id, capabilities.relativeHumidityMeasurement.humidity(humidity))
end
end

local matter_driver_template = {
lifecycle_handlers = {
init = device_init,
Expand Down Expand Up @@ -1249,6 +1308,14 @@ local matter_driver_template = {
},
[clusters.Switch.ID] = {
[clusters.Switch.attributes.MultiPressMax.ID] = max_press_handler
},
[clusters.RelativeHumidityMeasurement.ID] = {
[clusters.RelativeHumidityMeasurement.attributes.MeasuredValue.ID] = humidity_attr_handler
},
[clusters.TemperatureMeasurement.ID] = {
[clusters.TemperatureMeasurement.attributes.MeasuredValue.ID] = temperature_attr_handler,
[clusters.TemperatureMeasurement.attributes.MinMeasuredValue.ID] = temp_attr_handler_factory(TEMP_MIN),
[clusters.TemperatureMeasurement.attributes.MaxMeasuredValue.ID] = temp_attr_handler_factory(TEMP_MAX),
}
},
event = {
Expand Down Expand Up @@ -1302,6 +1369,14 @@ local matter_driver_template = {
},
[capabilities.powerMeter.ID] = {
clusters.ElectricalPowerMeasurement.attributes.ActivePower
},
[capabilities.relativeHumidityMeasurement.ID] = {
clusters.RelativeHumidityMeasurement.attributes.MeasuredValue
},
[capabilities.temperatureMeasurement.ID] = {
clusters.TemperatureMeasurement.attributes.MeasuredValue,
clusters.TemperatureMeasurement.attributes.MinMeasuredValue,
clusters.TemperatureMeasurement.attributes.MaxMeasuredValue
}
},
subscribed_events = {
Expand Down Expand Up @@ -1352,7 +1427,9 @@ local matter_driver_template = {
capabilities.powerConsumptionReport,
capabilities.valve,
capabilities.button,
capabilities.battery
capabilities.battery,
capabilities.temperatureMeasurement,
capabilities.relativeHumidityMeasurement
},
sub_drivers = {
require("eve-energy"),
Expand Down
Loading

0 comments on commit 7171fd3

Please sign in to comment.