-
Notifications
You must be signed in to change notification settings - Fork 473
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
add support for generic zigbee sensor #1921
base: main
Are you sure you want to change the base?
add support for generic zigbee sensor #1921
Conversation
Duplicate profile check: Passed - no duplicate profiles detected. |
Invitation URL: |
Test Results 65 files 410 suites 0s ⏱️ For more details on these failures, see this check. Results for commit 7a4d856. ♻️ This comment has been updated with latest results. |
Minimum allowed coverage is Generated by 🐒 cobertura-action against 7a4d856 |
@@ -0,0 +1,8 @@ | |||
zigbeeGeneric: | |||
- id: "ias-generic-sensor" | |||
deviceLabel: "IAS Zigbee Generic Sensor" |
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.
@@ -0,0 +1,12 @@ | |||
name: ias-generic-button-profile |
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.
If this profile is unnecessary, please remove.
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.
got it
|
||
local ZIGBEE_GENERIC_SENSOR_PROFILE = "ias-generic-sensor" | ||
local ZIGBEE_GENERIC_CONTACT_SENSOR_PROFILE = "ias-generic-contact-sensor" | ||
local ZIGBEE_GENERIC_EMERGENCY_BUTTON_PROFILE = "ias-generic-emergency-button" |
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.
You can remove this because there is no any implementation about button functionality in this code.
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.
got it
local profile = ZIGBEE_GENERIC_SENSOR_PROFILE | ||
if zone_type == Contact_Switch then | ||
profile = ZIGBEE_GENERIC_CONTACT_SENSOR_PROFILE | ||
elseif zone_type == Remote_Control or zone_type == Key_Fob or zone_type == Keypad then |
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.
You can remove this because there is no any implementation about button functionality in this code.
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.
Okay
state_change = true | ||
} | ||
|
||
log.info("---zone_status: "..zone_status.value) |
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.
You can remove log.info() after you have finished the test.
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.
Okay
local ZONETYPE = "ZoneType" | ||
local log = require "log" | ||
|
||
local Contact_Switch = 21 -- 0x0015 |
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.
You can use 0x0015 directly and use a capital letter when you define.
local CONTACT_SWITCH = 0x0015
local REMOTE_CONTROL = 0x010F
name: ias-generic-contact-sensor | ||
components: | ||
- id: main | ||
capabilities: |
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.
Would you test the battery capability for Group2 devices?
and check the configureReport set for the powerConfiguration cluster. (don't forget to add capabilities.battery in supported_capabilities of init.lua.)
Sensor should report its battery state periodically.
local ZIGBEE_GENERIC_MOTION_SENSOR_PROFILE = "ias-generic-motion-sensor" | ||
local ZIGBEE_GENERIC_WATERLEAK_SENSOR_PROFILE = "ias-generic-waterleak-sensor" | ||
|
||
-----add by dzd 20250124 start----- |
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.
these comments can be removed
end | ||
|
||
-- since we don't have button devices using IASZone, the driver here is remaining to be updated | ||
local generate_event_from_zone_status = function(driver, device, zone_status, zb_rx) |
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.
Instead of having a single function here that that branches, the standard way to handle this in drivers is with subdrivers. So if you had a subdriver that looked like:
local capabilities = require "st.capabilities"
local clusters = require "st.zigbee.zcl.clusters"
local IASZone = clusters.IASZone
local subdriver_template
local generate_event_from_zone_status = function(driver, device, zone_status, zb_rx)
if zone_status:is_alarm1_set() then
device:emit_event(capabilities.contactSensor.contact.open())
else
device:emit_event(capabilities.contactSensor.contact.closed())
end
end
local function subdriver_canhandle(opts, driver, device)
-- Create a "fields.lua" to contain this string definition and contact switch constant
return device:get_field("ZoneType") == 0x0015, subdriver_template
end
-- These functions could be moved to a common file as well.
local ias_zone_status_attr_handler = function(driver, device, zone_status, zb_rx)
generate_event_from_zone_status(driver, device, zone_status, zb_rx)
end
local ias_zone_status_change_handler = function(driver, device, zb_rx)
generate_event_from_zone_status(driver, device, zb_rx.body.zcl_body.zone_status, zb_rx)
end
subdriver_template = {
NAME = "Zigbee Contact",
zigbee_handlers = {
attr = {
[IASZone.ID] = {
[IASZone.attributes.ZoneStatus.ID] = ias_zone_status_attr_handler
}
},
cluster = {
[IASZone.ID] = {
[IASZone.client.commands.ZoneStatusChangeNotification.ID] = ias_zone_status_change_handler
}
}
},
can_handle = subdriver_canhandle
}
return subdriver_template
There will be a bit more duplicate code, but the it allows us to separate all the different types into their own files, so if we need more complicated logic we don't end up with a big mess of a function.
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.
@pInksenberg
For this, we need to check the ZoneType can be determined before the 'can_handle' triggered.
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.
In this driver, we can seperate sub driver following zonetype, but this edge driver read zone type in add_handler. so this device wouldn't likely to handle some message in initial time potentially.
local additional_fields = { | ||
state_change = true | ||
} |
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.
You should not be setting state_change = true
. That is only necessary, and should only be done for devices where they will emit the same value, but still need to be processed, like a button press.
@@ -0,0 +1,6 @@ | |||
name: 'Zigbee Sensor' |
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.
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.
I think it's OK as is
52d5eca
to
7320dbe
Compare
capabilities: | ||
- id: contactSensor | ||
version: 1 | ||
- id: batteryLevel |
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.
battery level is different than battery. All other Zigbee devices use the battery capability and that's what the defaults support not batteryLevel
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.
@varzac @tpmanley
SRCN tried to use the battery capability but the result was untrustworthy.
So they removed the battery capabilty at the beginning, but I think If we cannot accurately display battery percentage, showing battery level (normal/warning/critical) instead would greatly benefit users.
SRCN suggested to use the zoneStatus(zone_status:is_battery_low_set()) because these devices are working based on IAS zone cluster. It is nice suggestion. Now, batteryLevel has 3 conditions.(normal/warning/critical) and we can know two battery condition with zoneStatus(1 – Low battery / 0 – Battery OK), so I think we can match the 'low battery' state to 'warning' state in batteryLevel. What do you think of this?
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.
I left a somewhat similar comment here: https://github.com/SmartThingsCommunity/SmartThingsEdgeDrivers/pull/1921/files#r1956324647.
Was the BatteryPercentageRemaining
attribute found to not be trustworthy? We've found that usually works well, and the problems arise when trying to make BatteryVoltage
to a percentage as that's very hard to do, especially for coin cell batteries that have a pretty flat voltage for most of their life and then quickly decrease at the end. I would suggest using BatteryPercentageRemaining
and the battery
capability and/or ZoneStatus low battery to indicate warning
like you suggested (I don't have a strong preference whether it should be warning or critical).
7320dbe
to
6771cba
Compare
6771cba
to
7a4d856
Compare
-- test.mock_time.advance_time(50000) | ||
-- test.socket.zigbee:__set_channel_ordering("relaxed") | ||
-- test.socket.zigbee:__expect_send({ mock_device_waterleak_sensor.id, IASZone.attributes.ZoneStatus:read(mock_device_waterleak_sensor) }) | ||
-- test.wait_for_events() |
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.
Hi, @greens @varzac
I tried to add these three pieces of code in this file.
I found that this has relationship to the capabilities in supported_capabilities
in init.lua
.
However, when I add capabilities contactSensor
, motionSensor
and waterSensor
in file init.lua
(the commented-out code), I found that only the front one can work and the others failed. Why did this happen?
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.
Can you clarify what the failure is. Looking at the driver, there is no code that will send a ZoneStatus read after a delay. If you are expecting the infoChanged
to happen, in the test environment that will only happen if you write test code to generate it. In addition, I don't think sending a read on the infoChanged
is correct behavior.
capabilities.refresh | ||
-- capabilities.motionSensor, | ||
-- capabilities.contactSensor, | ||
-- capabilities.waterSensor |
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.
Only the motionSensor
here can work.
end | ||
|
||
-- ask device to upload its zone status, then the status of capabilities can be synchronized | ||
local ias_info_changed = function(driver, device) |
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.
This function will be run every time the device is updated on the cloud side. You should not be reading an attribute here. If the intent is for this to happen at some point after the device is added, you should use the call_with_delay
to have the driver wait some period and then send the read.
event = capabilities.contactSensor.contact.closed() | ||
end | ||
elseif type == MOTION_SENSOR then | ||
if zone_status:is_alarm1_set() then |
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.
Motion sensors can use either alarm1 or alarm2 so I would suggest reporting active
if either are set
local type = device:get_field(ZONETYPE) | ||
local event | ||
if type == CONTACT_SWITCH then | ||
if zone_status:is_alarm1_set() then |
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.
The ZCL spec says that contact switches can use both alarm1 and alarm2 so I think both should be checked
|
||
local battery_level_handler = function(driver, device, value, zb_rx) | ||
local voltage = value.value | ||
if voltage <= 25 then |
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.
It's pretty difficult to accurately translate voltage to battery level without knowing the details of the device and battery technology. I'd either suggest using the low battery indicator in the IAS Zone Status and/or switching from batteryLevel
capability to battery
and looking at the BatteryPercentageRemaining
attribute instead of BatteryVoltage
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.
Apologies, I just saw the similar comment here: #1921 (comment)
Check all that apply
Type of Change
Checklist
Description of Change
Add support for generic Zigbee sensor base on IASZone type
Summary of Completed Tests