Skip to content

Commit 38eb644

Browse files
unify-automatedjmartinez-silabs
authored andcommitted
Pull request project-chip#502: UIC-2846: emulate attribute IdentifyType
Merge in WMN_TOOLS/matter from feature/UIC-2846_Emulate_attribute_IdentifyType_for_spec_compliance to silabs Squashed commit of the following: commit 6cda15c319dd762e38f7d78de2bb6d25da6fee82 Author: Dennis Jensen <[email protected]> Date: Tue Jan 17 14:29:30 2023 +0100 UIC-2846: emulate attribute IdentifyType Changes: * Added an interface for registering emulators for specific clusters. * Made two data variables/schemes in the cluster emulator for keeping control of clusters, attributes and commands to emulate. * Added unit tests of the cluster emulator. Problems with encoding, so that is not fully tested reading attributes through the emulator.
1 parent 4c229d2 commit 38eb644

File tree

11 files changed

+470
-20
lines changed

11 files changed

+470
-20
lines changed

silabs_examples/unify-matter-bridge/linux/BUILD.gn

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ config("unify-config") {
2727
include_dirs = [
2828
"src",
2929
"src/cluster_translator",
30+
"src/cluster_translator/emulations",
3031
"src/matter_node_state_monitor",
3132
"src/matter_wrappers",
3233
"src/device_type_mapper",
@@ -53,6 +54,7 @@ static_library("unify-matter-bridge-lib") {
5354
"src/cluster_translator/group_command_translator.cpp",
5455
"src/cluster_translator/group_translator.cpp",
5556
"src/cluster_translator/cluster_emulator.cpp",
57+
"src/cluster_translator/emulations/emulate_identify.cpp",
5658
"src/demo_uic_cli.cpp",
5759
"src/device_type_mapper/matter_device_translator.cpp",
5860
"src/device_type_mapper/matter_device_type_selection.cpp",

silabs_examples/unify-matter-bridge/linux/src/cluster_translator/cluster_emulator.cpp

+51-11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "cluster_revision_table.hpp"
1616
#include "sl_log.h"
1717
#include <attribute_state_cache.hpp>
18+
1819
#define LOG_TAG "cluster_emulator"
1920

2021
namespace unify::matter_bridge {
@@ -26,7 +27,7 @@ namespace unify::matter_bridge {
2627
using namespace chip::app;
2728
using namespace chip::app::Clusters;
2829

29-
static uint32_t read_cluster_revision(const ConcreteReadAttributePath & aPath)
30+
uint32_t ClusterEmulator::read_cluster_revision(const ConcreteReadAttributePath & aPath) const
3031
{
3132
if (zap_cluster_revisions.count(aPath.mClusterId))
3233
{
@@ -38,8 +39,9 @@ static uint32_t read_cluster_revision(const ConcreteReadAttributePath & aPath)
3839
}
3940
}
4041

41-
static uint32_t read_feature_map_revision(const ConcreteReadAttributePath & aPath)
42+
uint32_t ClusterEmulator::read_feature_map_revision(const ConcreteReadAttributePath & aPath) const
4243
{
44+
sl_log_debug(LOG_TAG, "Reading feature map for cluster %d", aPath.mClusterId);
4345
switch (aPath.mClusterId)
4446
{
4547
case ColorControl::Id: {
@@ -57,6 +59,7 @@ static uint32_t read_feature_map_revision(const ConcreteReadAttributePath & aPat
5759
}
5860
break;
5961
case OnOff::Id:
62+
sl_log_debug(LOG_TAG, "Returning feature map for OnOff %d", ON_OFF_LIGHTING_FEATURE_MAP_MASK);
6063
return ON_OFF_LIGHTING_FEATURE_MAP_MASK;
6164
case LevelControl::Id:
6265
/// Check if OnOff is supported
@@ -70,19 +73,33 @@ static uint32_t read_feature_map_revision(const ConcreteReadAttributePath & aPat
7073
}
7174

7275
void ClusterEmulator::add_emulated_commands_and_attributes(
73-
const std::unordered_map<std::string, node_state_monitor::cluster> & unify_clusters,
74-
matter_cluster_builder & cluster_builder) const
76+
const node_state_monitor::cluster & unify_cluster,
77+
matter_cluster_builder & cluster_builder)
7578
{
7679
// We always need to add the feature map and cluster
7780
cluster_builder.attributes.push_back(EmberAfAttributeMetadata{ ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, ZCL_BITMAP32_ATTRIBUTE_TYPE,
7881
4, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() });
7982
cluster_builder.attributes.push_back(EmberAfAttributeMetadata{ ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID,
8083
ZCL_INT16U_ATTRIBUTE_TYPE, 2,
8184
ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() });
85+
86+
// Add emulation for commands and attributes for the cluster
87+
auto it = cluster_emulators_string_map.find(unify_cluster.cluster_name);
88+
if (it != cluster_emulators_string_map.end()) {
89+
auto emulated_result = it->second->emulate(unify_cluster, cluster_builder, cluster_emulators_attribute_id_map, cluster_emulators_command_id_map);
90+
if (emulated_result != CHIP_NO_ERROR) {
91+
sl_log_error(LOG_TAG, "Failed to add emulated commands and attributes for cluster %s", unify_cluster.cluster_name.c_str());
92+
}
93+
}
8294
}
8395

84-
bool ClusterEmulator::is_command_emulated(const ConcreteCommandPath &) const
85-
{
96+
bool ClusterEmulator::is_command_emulated(const ConcreteCommandPath & cPath) const
97+
{
98+
auto it = cluster_emulators_command_id_map.find(cPath.mClusterId);
99+
if (it != cluster_emulators_command_id_map.end())
100+
{
101+
return it->second.find(cPath.mCommandId) != it->second.end();
102+
}
86103
return false;
87104
}
88105

@@ -99,33 +116,56 @@ bool ClusterEmulator::is_attribute_emulated(const ConcreteAttributePath & aPath)
99116
;
100117
}
101118

119+
auto it = cluster_emulators_attribute_id_map.find(aPath.mClusterId);
120+
if (it != cluster_emulators_attribute_id_map.end())
121+
{
122+
return it->second.find(aPath.mAttributeId) != it->second.end();
123+
}
124+
102125
return false;
103126
}
104127

105128
CHIP_ERROR ClusterEmulator::invoke_command(CommandHandlerInterface::HandlerContext & handlerContext) const
106129
{
130+
if (is_command_emulated(handlerContext.mRequestPath))
131+
{
132+
return cluster_emulators_command_id_map.at(handlerContext.mRequestPath.mClusterId).at(handlerContext.mRequestPath.mCommandId)->command(handlerContext);
133+
}
134+
107135
return CHIP_ERROR_NOT_IMPLEMENTED;
108136
}
109137

110-
CHIP_ERROR ClusterEmulator::read_attribute(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) const
138+
CHIP_ERROR ClusterEmulator::read_attribute(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
111139
{
140+
sl_log_debug(LOG_TAG, "Reading attribute %d", aPath.mAttributeId);
112141
switch (aPath.mAttributeId)
113142
{
114-
case 0xFFFD: // Cluster Revision
115-
return aEncoder.Encode(read_cluster_revision(aPath));
116-
case 0xFFFC: // FeatureMap
117-
return aEncoder.Encode(read_feature_map_revision(aPath));
143+
case ZCL_CLUSTER_REVISION_SERVER_ATTRIBUTE_ID: // Cluster Revision
144+
return aEncoder.Encode(this->read_cluster_revision(aPath));
145+
case ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID: // FeatureMap
146+
return aEncoder.Encode(this->read_feature_map_revision(aPath));
118147
case 0xFFFE: // EventList
119148
return aEncoder.Encode(0);
120149
default:;
121150
;
122151
}
152+
153+
sl_log_debug(LOG_TAG, "Cluster specific attribute emulation attribute id %d for cluster id", aPath.mAttributeId, aPath.mClusterId);
154+
if (is_attribute_emulated(aPath))
155+
{
156+
return cluster_emulators_attribute_id_map.at(aPath.mClusterId).at(aPath.mAttributeId)->read_attribute(aPath, aEncoder);
157+
}
123158

124159
return CHIP_ERROR_INVALID_ARGUMENT;
125160
}
126161

127162
CHIP_ERROR ClusterEmulator::write_attribute(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) const
128163
{
164+
if (is_attribute_emulated(aPath))
165+
{
166+
return cluster_emulators_attribute_id_map.at(aPath.mClusterId).at(aPath.mAttributeId)->write_attribute(aPath, aDecoder);
167+
}
168+
129169
return CHIP_ERROR_NOT_IMPLEMENTED;
130170
}
131171
} // namespace unify::matter_bridge

silabs_examples/unify-matter-bridge/linux/src/cluster_translator/cluster_emulator.hpp

+24-6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717

1818
#include "matter_endpoint_builder.hpp"
1919
#include "unify_node_state_monitor.hpp"
20+
21+
// Emulation of commands and attributes
22+
#include "emulator.hpp"
23+
#include "emulate_identify.hpp"
24+
25+
2026
namespace unify::matter_bridge {
2127

2228
/**
@@ -28,15 +34,18 @@ namespace unify::matter_bridge {
2834
class ClusterEmulator
2935
{
3036
public:
37+
ClusterEmulator() {
38+
cluster_emulators_string_map["Identify"] = new EmulateIdentify();
39+
};
40+
3141
/**
3242
* @brief Add command and attributes to the clusters on the endpoint
3343
*
3444
* This function will all the commands and clusters to endpoint descriptor
3545
* which the endpoint_builder holds. Which commands an attributes are
3646
* emulated can be checked with is_command_emulated and is_attribute_emulated
3747
*/
38-
void add_emulated_commands_and_attributes(const std::unordered_map<std::string, node_state_monitor::cluster> & unify_clusters,
39-
matter_cluster_builder &) const;
48+
void add_emulated_commands_and_attributes(const node_state_monitor::cluster & unify_clusters, matter_cluster_builder &);
4049

4150
/**
4251
* @brief Check if a command is emulated
@@ -58,10 +67,10 @@ class ClusterEmulator
5867
* @brief Execute an emulated command
5968
*
6069
* @param handlerContext
61-
* @return
70+
* @return
6271
* - CHIP_ERROR_OK if the command was successfully emulated.
6372
* - CHIP_ERROR_NOT_IMPLEMENTED If the command is not emulated
64-
*
73+
*
6574
*/
6675
CHIP_ERROR invoke_command(chip::app::CommandHandlerInterface::HandlerContext & handlerContext) const;
6776

@@ -75,20 +84,29 @@ class ClusterEmulator
7584
* - CHIP_ERROR_NOT_IMPLEMENTED If the attribute is not emulated
7685
*/
7786
CHIP_ERROR read_attribute(const chip::app::ConcreteReadAttributePath & aPath,
78-
chip::app::AttributeValueEncoder & aEncoder) const;
87+
chip::app::AttributeValueEncoder & aEncoder);
7988

8089
/**
8190
* @brief Write an emulated attribute
8291
*
8392
* @param aPath
8493
* @param aDecoder
85-
* @return
94+
* @return
8695
* - CHIP_ERROR_OK write was successfully emulated.
8796
* - CHIP_ERROR_WRITE_FAILED the attribute is not writable.
8897
* - CHIP_ERROR_NOT_IMPLEMENTED If the attribute is not emulated
8998
*/
9099
CHIP_ERROR write_attribute(const chip::app::ConcreteDataAttributePath & aPath,
91100
chip::app::AttributeValueDecoder & aDecoder) const;
101+
102+
private:
103+
// Emulation functions
104+
uint32_t read_feature_map_revision(const ConcreteReadAttributePath & aPath) const;
105+
uint32_t read_cluster_revision(const ConcreteReadAttributePath & aPath) const;
106+
107+
std::map<chip::ClusterId, std::map<chip::AttributeId, EmulatorInterface *>> cluster_emulators_attribute_id_map;
108+
std::map<chip::ClusterId, std::map<chip::CommandId, EmulatorInterface *>> cluster_emulators_command_id_map;
109+
std::map<std::string, EmulatorInterface *> cluster_emulators_string_map;
92110
};
93111

94112
} // namespace unify::matter_bridge
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/******************************************************************************
2+
* # License
3+
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
4+
******************************************************************************
5+
* The licensor of this software is Silicon Laboratories Inc. Your use of this
6+
* software is governed by the terms of Silicon Labs Master Software License
7+
* Agreement (MSLA) available at
8+
* www.silabs.com/about-us/legal/master-software-license-agreement. This
9+
* software is distributed to you in Source Code format and is governed by the
10+
* sections of the MSLA applicable to Source Code.
11+
*
12+
*****************************************************************************/
13+
14+
#include "emulate_identify.hpp"
15+
16+
// UIC
17+
#include "sl_log.h"
18+
19+
// Matter
20+
#include <app-common/zap-generated/cluster-enums.h>
21+
22+
// Standard library
23+
#include <map>
24+
25+
namespace unify::matter_bridge {
26+
27+
using namespace chip::app;
28+
using namespace chip::app::Clusters;
29+
30+
#define LOG_TAG "EmulateIdentify"
31+
32+
CHIP_ERROR EmulateIdentify::emulate(
33+
const node_state_monitor::cluster & unify_cluster, matter_cluster_builder & cluster_builder,
34+
std::map<chip::ClusterId, std::map<chip::AttributeId, EmulatorInterface *>> & emulation_attribute_handler_map,
35+
std::map<chip::ClusterId, std::map<chip::CommandId, EmulatorInterface *>> & emulation_command_handler)
36+
{
37+
// Identify cluster emulation handler registered for IdentifyType attribute
38+
sl_log_debug(LOG_TAG, "Emulating IdentifyType attribute for Identify cluster");
39+
emulation_attribute_handler_map[Identify::Id][Identify::Attributes::IdentifyType::Id] = this;
40+
41+
// Add IdentifyType attribute to the matter cluster
42+
cluster_builder.attributes.push_back(EmberAfAttributeMetadata{ Identify::Attributes::IdentifyType::Id, ZCL_ENUM8_ATTRIBUTE_ID,
43+
1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() });
44+
45+
return CHIP_NO_ERROR;
46+
}
47+
48+
CHIP_ERROR EmulateIdentify::read_attribute(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
49+
{
50+
sl_log_debug(LOG_TAG, "Read IdentifyType attribute");
51+
52+
// IdentifyType is a mandatory attribute we default it to None
53+
if (aPath.mAttributeId == Identify::Attributes::IdentifyType::Id)
54+
{
55+
return aEncoder.Encode(Identify::IdentifyIdentifyType::EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_NONE);
56+
}
57+
58+
sl_log_warning(LOG_TAG, "Emulation identify activated for unknown attribute id %d under cluster id %d", aPath.mAttributeId,
59+
aPath.mClusterId);
60+
return CHIP_ERROR_INVALID_ARGUMENT;
61+
}
62+
63+
} // namespace unify::matter_bridge
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/******************************************************************************
2+
* # License
3+
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
4+
******************************************************************************
5+
* The licensor of this software is Silicon Laboratories Inc. Your use of this
6+
* software is governed by the terms of Silicon Labs Master Software License
7+
* Agreement (MSLA) available at
8+
* www.silabs.com/about-us/legal/master-software-license-agreement. This
9+
* software is distributed to you in Source Code format and is governed by the
10+
* sections of the MSLA applicable to Source Code.
11+
*
12+
*****************************************************************************/
13+
14+
#ifndef EMULATE_IDENTIFY_HPP
15+
#define EMULATE_IDENTIFY_HPP
16+
17+
// Emulator interface
18+
#include "emulator.hpp"
19+
20+
namespace unify::matter_bridge {
21+
22+
using namespace chip::app;
23+
using namespace chip::app::Clusters;
24+
25+
class EmulateIdentify : public EmulatorInterface
26+
{
27+
public:
28+
/**
29+
* @brief Emulate Identify cluster this will emulate defined commands and
30+
* attributes
31+
*
32+
* @param unify_cluster
33+
* @param cluster_builder
34+
* @param emulation_handler_map
35+
* @return CHIP_ERROR
36+
*/
37+
CHIP_ERROR
38+
emulate(const node_state_monitor::cluster & unify_cluster, matter_cluster_builder & cluster_builder,
39+
std::map<chip::ClusterId, std::map<chip::AttributeId, EmulatorInterface *>> & emulation_attribute_handler_map,
40+
std::map<chip::ClusterId, std::map<chip::CommandId, EmulatorInterface *>> & emulation_command_handler) override;
41+
42+
/**
43+
* @brief Read the emulated IdentifyType attribute
44+
*
45+
* @param aPath
46+
* @param aEncoder
47+
* @return CHIP_ERROR
48+
*/
49+
CHIP_ERROR read_attribute(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
50+
};
51+
52+
} // namespace unify::matter_bridge
53+
54+
#endif // EMULATE_IDENTIFY_HPP

0 commit comments

Comments
 (0)