Skip to content
Merged
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
24 changes: 24 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ on:
types: [opened, synchronize, labeled, unlabeled]
paths:
- 'drivers/**'
- 'tools/run_driver_tests.py'
- 'tools/run_driver_tests_p.py'

jobs:
# Two separate jobs for finding the right artifact to run tests with
Expand Down Expand Up @@ -91,11 +93,33 @@ jobs:
- run: echo ${{ steps.changed-drivers.outputs.all_modified_files }}
- name: Install Python requirements
run: pip install -r tools/requirements.txt
- name: Fetch capability definitions
continue-on-error: true
run: |
python3 tools/fetch_capability_definitions.py \
--drivers-dir ${{ github.workspace }}/drivers \
--output-dir ${{ github.workspace }}/capability_json \
--failed-output-file ${{ github.workspace }}/capability_failures_comment.md
env:
CAPABILITY_PAT: ${{ secrets.CAPABILITY_DEFINITIONS_PAT }}
- name: Report capability download failures
if: hashFiles('capability_failures_comment.md') != '' && always()
uses: marocchino/sticky-pull-request-comment@v2
with:
path: ${{ github.workspace }}/capability_failures_comment.md
header: capability-download-failures
- name: Clear capability download failures comment
if: hashFiles('capability_failures_comment.md') == '' && always()
uses: marocchino/sticky-pull-request-comment@v2
with:
header: capability-download-failures
delete: true
- name: Run the tests
id: run-tests
run: python tools/run_driver_tests_p.py ${{ steps.changed-drivers.outputs.all_modified_files }}
env:
LUA_PATH: ${{ steps.lua_path.outputs.lua_path }}
ST_CAPABILITY_JSON_DIR: ${{ github.workspace }}/capability_json
- name: Upload test artifact
if: always()
uses: actions/upload-artifact@v4
Expand Down
6 changes: 6 additions & 0 deletions drivers/SmartThings/matter-lock/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ matterManufacturer:
vendorId: 0x152C
productId: 0x9501
deviceProfileName: lock
#Lockly
- id: "5212/2"
deviceLabel: Lockly Smart Lock
vendorId: 0x145C
productId: 0x0002
deviceProfileName: lock-modular
matterGeneric:
- id: "matter/door-lock"
deviceLabel: Matter Door Lock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,31 @@ EnergyMeasurementStruct.field_defs = {
is_optional = true,
data_type = require "st.matter.data_types.Uint64",
},
{
name = "apparent_energy",
field_id = 5,
is_nullable = false,
is_optional = true,
data_type = require "st.matter.data_types.Int64",
},
{
name = "reactive_energy",
field_id = 6,
is_nullable = false,
is_optional = true,
data_type = require "st.matter.data_types.Int64",
},
}

EnergyMeasurementStruct.init = function(cls, tbl)
local o = {}
o.elements = {}
o.num_elements = 0
setmetatable(o, new_mt)
for idx, field_def in ipairs(cls.field_defs) do
for _idx, field_def in ipairs(cls.field_defs) do
if (not field_def.is_optional and not field_def.is_nullable) and not tbl[field_def.name] then
error("Missing non optional or non_nullable field: " .. field_def.name)
else
elseif not (field_def.is_optional and tbl[field_def.name] == nil) then
o.elements[field_def.name] = data_types.validate_or_build_type(tbl[field_def.name], field_def.data_type, field_def.name)
o.elements[field_def.name].field_id = field_def.field_id
o.num_elements = o.num_elements + 1
Expand All @@ -71,19 +85,19 @@ new_mt.__index.serialize = EnergyMeasurementStruct.serialize
EnergyMeasurementStruct.augment_type = function(self, val)
local elems = {}
local num_elements = 0
for _, v in pairs(val.elements) do
for _, v in pairs(val.elements or {}) do
for _, field_def in ipairs(self.field_defs) do
if field_def.field_id == v.field_id and
field_def.is_nullable and
(v.value == nil and v.elements == nil) then
elems[field_def.name] = data_types.validate_or_build_type(v, data_types.Null, field_def.field_name)
num_elements = num_elements + 1
elseif field_def.field_id == v.field_id and not
(field_def.is_optional and v.value == nil) then
(field_def.is_optional and v.value == nil and v.elements == nil) then
elems[field_def.name] = data_types.validate_or_build_type(v, field_def.data_type, field_def.field_name)
num_elements = num_elements + 1
if field_def.element_type ~= nil then
for i, e in ipairs(elems[field_def.name].elements) do
for i, e in ipairs(elems[field_def.name].elements or {}) do
elems[field_def.name].elements[i] = data_types.validate_or_build_type(e, field_def.element_type)
end
end
Expand Down
5 changes: 5 additions & 0 deletions drivers/SmartThings/matter-switch/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ if version.api < 16 then
clusters.Descriptor = require "embedded_clusters.Descriptor"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local SwitchLifecycleHandlers = {}

function SwitchLifecycleHandlers.device_added(driver, device)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ if version.api < 11 then
clusters.PowerTopology = require "embedded_clusters.PowerTopology"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local AttributeHandlers = {}

-- [[ ON OFF CLUSTER ATTRIBUTES ]] --
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ if version.api < 11 then
clusters.ValveConfigurationAndControl = require "embedded_clusters.ValveConfigurationAndControl"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local DeviceConfiguration = {}
local ChildConfiguration = {}
local SwitchDeviceConfiguration = {}
Expand Down Expand Up @@ -87,7 +92,9 @@ function SwitchDeviceConfiguration.assign_profile_for_onoff_ep(device, server_on
local generic_profile = fields.device_type_profile_map[primary_dt_id]

local static_electrical_tags = switch_utils.get_field_for_endpoint(device, fields.ELECTRICAL_TAGS, server_onoff_ep_id)
if static_electrical_tags ~= nil then
if type(static_electrical_tags) == "string" then
-- if no associated profile is found for the device type and static electrical tags are available, use "plug-binary" as a fallback
generic_profile = generic_profile or "plug-binary"
-- profiles like 'light-binary' and 'plug-binary' should drop the '-binary' and become 'light-power', 'plug-energy-powerConsumption', etc.
generic_profile = string.gsub(generic_profile, "-binary", "") .. static_electrical_tags
end
Expand Down
20 changes: 16 additions & 4 deletions drivers/SmartThings/matter-switch/src/switch_utils/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ if version.api < 16 then
clusters.Descriptor = require "embedded_clusters.Descriptor"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local utils = {}

function utils.tbl_contains(array, value)
Expand Down Expand Up @@ -545,16 +550,14 @@ function utils.subscribe(device)
devices_seen[checked_device.id] = true -- only loop through any device once
end
end
-- The refresh capability command handler in the lua libs uses this key to determine which attributes to read. Note
-- that only attributes_seen needs to be saved here, and not events_seen, since the refresh handler only checks
-- attributes and not events.
device:set_field(fields.SUBSCRIBED_ATTRIBUTES_KEY, attributes_seen)

-- If the type of battery support has not yet been determined, add the PowerSource AttributeList to the list of
-- subscribed attributes in order to determine which if any battery capability should be used.
if device:get_field(fields.profiling_data.BATTERY_SUPPORT) == nil then
local ib = im.InteractionInfoBlock(nil, clusters.PowerSource.ID, clusters.PowerSource.attributes.AttributeList.ID)
subscribe_request:with_info_block(ib)
attributes_seen[clusters.PowerSource.ID] = attributes_seen[clusters.PowerSource.ID] or {}
attributes_seen[clusters.PowerSource.ID][clusters.PowerSource.attributes.AttributeList.ID] = ib
end

-- If the power topology of the device has not yet been determined, add the AvailableEndpoints (for SET topology)
Expand All @@ -566,12 +569,21 @@ function utils.subscribe(device)
if clusters.PowerTopology.are_features_supported(clusters.PowerTopology.types.Feature.SET_TOPOLOGY, endpoint_power_topology_cluster.feature_map or 0) then
local ib = im.InteractionInfoBlock(nil, clusters.PowerTopology.ID, clusters.PowerTopology.attributes.AvailableEndpoints.ID)
subscribe_request:with_info_block(ib)
attributes_seen[clusters.PowerTopology.ID] = attributes_seen[clusters.PowerTopology.ID] or {}
attributes_seen[clusters.PowerTopology.ID][clusters.PowerTopology.attributes.AvailableEndpoints.ID] = ib
elseif clusters.PowerTopology.are_features_supported(clusters.PowerTopology.types.Feature.TREE_TOPOLOGY, endpoint_power_topology_cluster.feature_map or 0) then
local ib = im.InteractionInfoBlock(nil, clusters.Descriptor.ID, clusters.Descriptor.attributes.PartsList.ID)
subscribe_request:with_info_block(ib)
attributes_seen[clusters.Descriptor.ID] = attributes_seen[clusters.Descriptor.ID] or {}
attributes_seen[clusters.Descriptor.ID][clusters.Descriptor.attributes.PartsList.ID] = ib
end
end

-- The refresh capability command handler in the lua libs uses this key to determine which attributes to read. Note
-- that only attributes_seen needs to be saved here, and not events_seen, since the refresh handler only checks
-- attributes and not events.
device:set_field(fields.SUBSCRIBED_ATTRIBUTES_KEY, attributes_seen)

if #subscribe_request.info_blocks > 0 then
device:send(subscribe_request)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ if version.api < 11 then
clusters.PowerTopology = require "embedded_clusters.PowerTopology"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local aqara_parent_ep = 4
local aqara_child1_ep = 1
local aqara_child2_ep = 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ if version.api < 11 then
clusters.PowerTopology = require "embedded_clusters.PowerTopology"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local mock_device = test.mock_device.build_test_matter_device({
profile = t_utils.get_profile_definition("plug-level-power-energy-powerConsumption.yml"),
manufacturer_info = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ if version.api < 16 then
clusters.Descriptor = require "embedded_clusters.Descriptor"
end

-- Catch nil elements errors gracefully without receiving a coroutine error
if version.api < 21 then
clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct = require "embedded_clusters.ElectricalEnergyMeasurement.types.EnergyMeasurementStruct"
end

local mock_device = test.mock_device.build_test_matter_device({
profile = t_utils.get_profile_definition("plug-level-power-energy-powerConsumption.yml"),
manufacturer_info = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ local cluster_base = require "st.zigbee.cluster_base"
local data_types = require "st.zigbee.data_types"
local t_utils = require "integration_test.utils"
local zigbee_test_utils = require "integration_test.zigbee_test_utils"
local custom_capabilities = require "shus-mattress/custom_capabilities"

local shus_mattress_profile_def = t_utils.get_profile_definition("shus-smart-mattress.yml")
test.add_package_capability("aiMode.yaml")
Expand All @@ -18,6 +17,8 @@ test.add_package_capability("strongExpMode.yaml")
test.add_package_capability("yoga.yaml")
test.add_package_capability("mattressHardness.yaml")

local custom_capabilities = require "shus-mattress/custom_capabilities"

local PRIVATE_CLUSTER_ID = 0xFCC2
local MFG_CODE = 0x1235

Expand Down
4 changes: 2 additions & 2 deletions drivers/SmartThings/zigbee-switch/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2542,9 +2542,9 @@ zigbeeManufacturer:
manufacturer: FIRSTLED
model: M2S2BAC
deviceProfileName: switch-light-restore-wireless
- id: "ManDai Technology/DC2DC12MiV1"
- id: "FIRSTLED/DC2DC12MiV1"
deviceLabel: Easy-Fit Driver
manufacturer: ManDai Technology
manufacturer: FIRSTLED
model: DC2DC12MiV1
deviceProfileName: light-color-temp-time-restore
zigbeeGeneric:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
-- Licensed under the Apache License, Version 2.0

return {
{ mfr = "ManDai Technology", model = "DC2DC12MiV1" }
{ mfr = "FIRSTLED", model = "DC2DC12MiV1" }
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ local mock_device = test.mock_device.build_test_zigbee_device(
zigbee_endpoints = {
[1] = {
id = 1,
manufacturer = "ManDai Technology",
manufacturer = "FIRSTLED",
model = "DC2DC12MiV1",
server_clusters = { 0x0006, 0x0008, 0x0300 }
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/SmartThings/zwave-switch/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ zwaveManufacturer:
productId: 0xC001
deviceProfileName: smartplug-binary
- id: 0312/FF00/FF07
deviceLabel: Minoston Outlet
deviceLabel: Smart Plug
manufacturerId: 0x0312
productType: 0xFF00
productId: 0xFF07
Expand Down
Loading
Loading