From f98ac9786ccb292c3604020f10168935fef079ad Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 26 Jul 2021 15:31:53 -0700 Subject: [PATCH 01/10] Definition for AdministratorCommissioning cluster --- .../administrator-commissioning-cluster.xml | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/app/zap-templates/zcl/data-model/chip/administrator-commissioning-cluster.xml diff --git a/src/app/zap-templates/zcl/data-model/chip/administrator-commissioning-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/administrator-commissioning-cluster.xml new file mode 100644 index 00000000000000..1dd8944e50e884 --- /dev/null +++ b/src/app/zap-templates/zcl/data-model/chip/administrator-commissioning-cluster.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + AdministratorCommissioning + General + 0x003c + ADMINISTRATOR_COMMISSIONING_CLUSTER + Commands to trigger a Node to allow a new Administrator to commission it. + + + This command is used by a current Administrator to instruct a Node to go into commissioning mode using enhanced commissioning method. + + + + + + + + + + This command is used by a current Administrator to instruct a Node to go into commissioning mode using basic commissioning method, if the node supports it. + + + + + This command is used by a current Administrator to instruct a Node to revoke any active Open Commissioning Window or Open Basic Commissioning Window command. + + + + From 82091dbb44ec450d0198503eed30e1e8fdaef20c Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 26 Jul 2021 16:06:21 -0700 Subject: [PATCH 02/10] generated code and updated build files --- .../all-clusters-common/all-clusters-app.zap | 77 + .../gen/IMClusterCommandHandler.cpp | 200 ++ .../all-clusters-common/gen/callback-stub.cpp | 8 + .../all-clusters-common/gen/endpoint_config.h | 107 +- .../all-clusters-common/gen/gen_config.h | 6 + .../esp32/main/CMakeLists.txt | 1 + .../bridge-app/bridge-common/bridge-app.zap | 94 +- .../gen/IMClusterCommandHandler.cpp | 200 ++ .../bridge-common/gen/callback-stub.cpp | 8 + .../bridge-common/gen/endpoint_config.h | 29 +- .../bridge-app/bridge-common/gen/gen_config.h | 6 + .../chip-tool/commands/clusters/Commands.h | 202 ++ .../gen/IMClusterCommandHandler.cpp | 200 ++ .../lighting-common/gen/callback-stub.cpp | 8 + .../lighting-common/gen/endpoint_config.h | 31 +- .../lighting-common/gen/gen_config.h | 6 + .../lighting-common/lighting-app.zap | 77 + examples/lighting-app/mbed/CMakeLists.txt | 1 + .../lighting-app/nrfconnect/CMakeLists.txt | 1 + examples/lighting-app/telink/CMakeLists.txt | 1 + examples/lock-app/esp32/main/CMakeLists.txt | 1 + .../gen/IMClusterCommandHandler.cpp | 200 ++ .../lock-common/gen/callback-stub.cpp | 8 + .../lock-common/gen/endpoint_config.h | 25 +- .../lock-app/lock-common/gen/gen_config.h | 6 + examples/lock-app/lock-common/lock-app.zap | 3192 ++++++----------- examples/lock-app/mbed/CMakeLists.txt | 1 + examples/lock-app/nrfconnect/CMakeLists.txt | 1 + examples/pump-app/nrfconnect/CMakeLists.txt | 1 + .../gen/IMClusterCommandHandler.cpp | 200 ++ .../pump-common/gen/callback-stub.cpp | 8 + .../pump-common/gen/endpoint_config.h | 37 +- .../pump-app/pump-common/gen/gen_config.h | 6 + examples/pump-app/pump-common/pump-app.zap | 94 +- .../nrfconnect/CMakeLists.txt | 1 + .../gen/IMClusterCommandHandler.cpp | 200 ++ .../gen/callback-stub.cpp | 8 + .../gen/endpoint_config.h | 31 +- .../pump-controller-common/gen/gen_config.h | 6 + .../pump-controller-app.zap | 94 +- .../esp32/main/CMakeLists.txt | 1 + .../main/gen/IMClusterCommandHandler.cpp | 200 ++ .../esp32/main/gen/callback-stub.cpp | 8 + .../esp32/main/gen/endpoint_config.h | 25 +- .../esp32/main/gen/gen_config.h | 6 + .../esp32/main/temperature-measurement.zap | 2362 ++++-------- .../gen/IMClusterCommandHandler.cpp | 200 ++ .../thermostat-common/gen/callback-stub.cpp | 8 + .../thermostat-common/gen/endpoint_config.h | 101 +- .../thermostat-common/gen/gen_config.h | 6 + .../thermostat-common/thermostat.zap | 77 + .../tv-common/gen/IMClusterCommandHandler.cpp | 200 ++ .../tv-app/tv-common/gen/callback-stub.cpp | 8 + .../tv-app/tv-common/gen/endpoint_config.h | 69 +- examples/tv-app/tv-common/gen/gen_config.h | 6 + examples/tv-app/tv-common/tv-app.zap | 83 +- .../common/gen/IMClusterCommandHandler.cpp | 200 ++ .../window-app/common/gen/callback-stub.cpp | 8 + .../window-app/common/gen/endpoint_config.h | 25 +- examples/window-app/common/gen/gen_config.h | 6 + examples/window-app/common/window-app.zap | 77 + .../administrator-commissioning-server.cpp | 60 + src/app/common/gen/attribute-id.h | 6 + src/app/common/gen/callback.h | 165 + src/app/common/gen/client-command-macro.h | 36 + src/app/common/gen/cluster-id.h | 3 + src/app/common/gen/command-id.h | 5 + src/app/common/gen/enums.h | 8 + src/app/common/gen/ids/Clusters.h | 3 + src/app/common/gen/ids/Commands.h | 10 + src/app/common/gen/print-cluster.h | 8 + src/app/zap-templates/zcl/zcl.json | 1 + src/app/zap_cluster_list.py | 2 + .../data_model/controller-clusters.zap | 77 + .../data_model/gen/CHIPClusters.cpp | 160 + src/controller/data_model/gen/CHIPClusters.h | 21 + .../data_model/gen/callback-stub.cpp | 8 + .../data_model/gen/endpoint_config.h | 79 +- src/controller/data_model/gen/gen_config.h | 5 + src/controller/java/gen/CHIPClusters-JNI.cpp | 191 + src/controller/java/gen/ChipClusters.java | 59 + .../python/chip/clusters/CHIPClusters.cpp | 44 + .../python/chip/clusters/CHIPClusters.py | 48 + .../Framework/CHIP/gen/CHIPClustersObjc.h | 20 + .../Framework/CHIP/gen/CHIPClustersObjc.mm | 127 + .../Framework/CHIPTests/CHIPClustersTests.m | 21 + 86 files changed, 6367 insertions(+), 3859 deletions(-) create mode 100644 src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index 2ed4af9b2d86ef..1aa0aafc654d99 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -3215,6 +3215,83 @@ } ] }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "Operational Credentials", "code": 62, diff --git a/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp b/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp index a3d0e73dddb66b..70299109290a75 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp +++ b/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp @@ -51,6 +51,203 @@ void ReportCommandUnsupported(Command * aCommandObj, EndpointId aEndpointId, Clu namespace clusters { +namespace AdministratorCommissioning { + +void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, + TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case Clusters::AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow: { + expectArgumentCount = 1; + uint16_t CommissioningTimeout; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(aEndpointId, apCommandObj, + CommissioningTimeout); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow: { + expectArgumentCount = 6; + uint16_t CommissioningTimeout; + chip::ByteSpan PAKEVerifier; + uint16_t Discriminator; + uint32_t Iterations; + chip::ByteSpan Salt; + uint16_t PasscodeID; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + PAKEVerifier = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: + TLVUnpackError = aDataTlv.Get(Discriminator); + break; + case 3: + TLVUnpackError = aDataTlv.Get(Iterations); + break; + case 4: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + Salt = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 5: + TLVUnpackError = aDataTlv.Get(PasscodeID); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( + aEndpointId, apCommandObj, CommissioningTimeout, PAKEVerifier, Discriminator, Iterations, Salt, PasscodeID); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::RevokeCommissioning: { + + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(aEndpointId, apCommandObj); + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::AdministratorCommissioning::Id, aCommandId); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + Clusters::AdministratorCommissioning::Id, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT + ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError), + ChipError::FormatError(TLVUnpackError), currentDecodeTagId); + // A command with no arguments would never write currentDecodeTagId. If + // progress logging is also disabled, it would look unused. Silence that + // warning. + UNUSED_VAR(currentDecodeTagId); + } +} + +} // namespace AdministratorCommissioning + namespace BarrierControl { void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, @@ -7033,6 +7230,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case Clusters::AdministratorCommissioning::Id: + clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case Clusters::BarrierControl::Id: clusters::BarrierControl::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/all-clusters-app/all-clusters-common/gen/callback-stub.cpp b/examples/all-clusters-app/all-clusters-common/gen/callback-stub.cpp index 6a2b60293b187e..33c5ac999c6346 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/callback-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/gen/callback-stub.cpp @@ -31,6 +31,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_ACCOUNT_LOGIN_CLUSTER_ID: emberAfAccountLoginClusterInitCallback(endpoint); break; + case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID: + emberAfAdministratorCommissioningClusterInitCallback(endpoint); + break; case ZCL_APPLICATION_BASIC_CLUSTER_ID: emberAfApplicationBasicClusterInitCallback(endpoint); break; @@ -186,6 +189,11 @@ void __attribute__((weak)) emberAfAccountLoginClusterInitCallback(EndpointId end // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfApplicationBasicClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h b/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h index 5e8a471d558417..ccb82b8aa68dfe 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h +++ b/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h @@ -1945,7 +1945,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 380 +#define GENERATED_ATTRIBUTE_COUNT 381 #define GENERATED_ATTRIBUTES \ { \ \ @@ -2091,6 +2091,9 @@ { 0x0006, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(2712) }, /* OverrunCount */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0001, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(2720) }, /* fabrics list */ \ { 0x0002, ZAP_TYPE(INT8U), 1, 0, ZAP_EMPTY_DEFAULT() }, /* SupportedFabrics */ \ @@ -2501,7 +2504,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 54 +#define GENERATED_CLUSTER_COUNT 55 #define GENERATED_CLUSTERS \ { \ { \ @@ -2541,169 +2544,172 @@ 0x0037, ZAP_ATTRIBUTE_INDEX(108), 6, 42, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { \ - 0x003E, ZAP_ATTRIBUTE_INDEX(114), 4, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x003C, ZAP_ATTRIBUTE_INDEX(114), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { \ + 0x003E, ZAP_ATTRIBUTE_INDEX(115), 4, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { \ - 0x0405, ZAP_ATTRIBUTE_INDEX(118), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0405, ZAP_ATTRIBUTE_INDEX(119), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Relative Humidity Measurement (server) */ \ { \ - 0xF000, ZAP_ATTRIBUTE_INDEX(122), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0xF000, ZAP_ATTRIBUTE_INDEX(123), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Binding (server) */ \ { \ - 0xF004, ZAP_ATTRIBUTE_INDEX(123), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0xF004, ZAP_ATTRIBUTE_INDEX(124), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Group Key Management (server) */ \ { 0x0003, \ - ZAP_ATTRIBUTE_INDEX(126), \ + ZAP_ATTRIBUTE_INDEX(127), \ 2, \ 4, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayIdentifyServer }, /* Endpoint: 1, Cluster: Identify (server) */ \ { 0x0004, \ - ZAP_ATTRIBUTE_INDEX(128), \ + ZAP_ATTRIBUTE_INDEX(129), \ 2, \ 3, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayGroupsServer }, /* Endpoint: 1, Cluster: Groups (server) */ \ { 0x0005, \ - ZAP_ATTRIBUTE_INDEX(130), \ + ZAP_ATTRIBUTE_INDEX(131), \ 6, \ 8, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayScenesServer }, /* Endpoint: 1, Cluster: Scenes (server) */ \ { 0x0006, \ - ZAP_ATTRIBUTE_INDEX(136), \ + ZAP_ATTRIBUTE_INDEX(137), \ 7, \ 13, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOnOffServer }, /* Endpoint: 1, Cluster: On/off (server) */ \ { 0x0008, \ - ZAP_ATTRIBUTE_INDEX(143), \ + ZAP_ATTRIBUTE_INDEX(144), \ 5, \ 7, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayLevelControlServer }, /* Endpoint: 1, Cluster: Level Control (server) */ \ { \ - 0x000F, ZAP_ATTRIBUTE_INDEX(148), 4, 5, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x000F, ZAP_ATTRIBUTE_INDEX(149), 4, 5, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Binary Input (Basic) (server) */ \ { \ - 0x001D, ZAP_ATTRIBUTE_INDEX(152), 5, 1018, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x001D, ZAP_ATTRIBUTE_INDEX(153), 5, 1018, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Descriptor (server) */ \ { \ - 0x0039, ZAP_ATTRIBUTE_INDEX(157), 15, 855, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0039, ZAP_ATTRIBUTE_INDEX(158), 15, 855, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Bridged Device Basic (server) */ \ { \ - 0x003B, ZAP_ATTRIBUTE_INDEX(172), 3, 4, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x003B, ZAP_ATTRIBUTE_INDEX(173), 3, 4, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Switch (server) */ \ { \ - 0x0040, ZAP_ATTRIBUTE_INDEX(175), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0040, ZAP_ATTRIBUTE_INDEX(176), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Fixed Label (server) */ \ { 0x0101, \ - ZAP_ATTRIBUTE_INDEX(177), \ + ZAP_ATTRIBUTE_INDEX(178), \ 4, \ 5, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayDoorLockServer }, /* Endpoint: 1, Cluster: Door Lock (server) */ \ { \ - 0x0102, ZAP_ATTRIBUTE_INDEX(181), 19, 31, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0102, ZAP_ATTRIBUTE_INDEX(182), 19, 31, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Window Covering (server) */ \ { \ - 0x0103, ZAP_ATTRIBUTE_INDEX(200), 5, 7, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0103, ZAP_ATTRIBUTE_INDEX(201), 5, 7, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Barrier Control (server) */ \ { \ 0x0200, \ - ZAP_ATTRIBUTE_INDEX(205), \ + ZAP_ATTRIBUTE_INDEX(206), \ 8, \ 13, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayPumpConfigurationAndControlServer \ }, /* Endpoint: 1, Cluster: Pump Configuration and Control (server) */ \ { \ - 0x0201, ZAP_ATTRIBUTE_INDEX(213), 10, 17, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0201, ZAP_ATTRIBUTE_INDEX(214), 10, 17, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Thermostat (server) */ \ { 0x0300, \ - ZAP_ATTRIBUTE_INDEX(223), \ + ZAP_ATTRIBUTE_INDEX(224), \ 51, \ 336, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayColorControlServer }, /* Endpoint: 1, Cluster: Color Control (server) */ \ { \ - 0x0402, ZAP_ATTRIBUTE_INDEX(274), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0402, ZAP_ATTRIBUTE_INDEX(275), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Temperature Measurement (server) */ \ { \ - 0x0403, ZAP_ATTRIBUTE_INDEX(278), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0403, ZAP_ATTRIBUTE_INDEX(279), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Pressure Measurement (server) */ \ { \ - 0x0404, ZAP_ATTRIBUTE_INDEX(282), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0404, ZAP_ATTRIBUTE_INDEX(283), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Flow Measurement (server) */ \ { \ - 0x0405, ZAP_ATTRIBUTE_INDEX(286), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0405, ZAP_ATTRIBUTE_INDEX(287), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Relative Humidity Measurement (server) */ \ { 0x0406, \ - ZAP_ATTRIBUTE_INDEX(290), \ + ZAP_ATTRIBUTE_INDEX(291), \ 4, \ 5, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOccupancySensingServer }, /* Endpoint: 1, Cluster: Occupancy Sensing (server) */ \ { 0x0500, \ - ZAP_ATTRIBUTE_INDEX(294), \ + ZAP_ATTRIBUTE_INDEX(295), \ 6, \ 16, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION) | \ ZAP_CLUSTER_MASK(MESSAGE_SENT_FUNCTION), \ chipFuncArrayIasZoneServer }, /* Endpoint: 1, Cluster: IAS Zone (server) */ \ { \ - 0x0503, ZAP_ATTRIBUTE_INDEX(300), 2, 34, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0503, ZAP_ATTRIBUTE_INDEX(301), 2, 34, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Wake on LAN (server) */ \ { \ - 0x0504, ZAP_ATTRIBUTE_INDEX(302), 4, 320, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0504, ZAP_ATTRIBUTE_INDEX(303), 4, 320, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: TV Channel (server) */ \ { \ - 0x0505, ZAP_ATTRIBUTE_INDEX(306), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0505, ZAP_ATTRIBUTE_INDEX(307), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Target Navigator (server) */ \ { \ - 0x0506, ZAP_ATTRIBUTE_INDEX(308), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0506, ZAP_ATTRIBUTE_INDEX(309), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Media Playback (server) */ \ { \ - 0x0507, ZAP_ATTRIBUTE_INDEX(309), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0507, ZAP_ATTRIBUTE_INDEX(310), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Media Input (server) */ \ { \ - 0x0508, ZAP_ATTRIBUTE_INDEX(312), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0508, ZAP_ATTRIBUTE_INDEX(313), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Low Power (server) */ \ { \ - 0x0509, ZAP_ATTRIBUTE_INDEX(313), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0509, ZAP_ATTRIBUTE_INDEX(314), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Keypad Input (server) */ \ { \ - 0x050A, ZAP_ATTRIBUTE_INDEX(314), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050A, ZAP_ATTRIBUTE_INDEX(315), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Content Launcher (server) */ \ { \ - 0x050B, ZAP_ATTRIBUTE_INDEX(317), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050B, ZAP_ATTRIBUTE_INDEX(318), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Audio Output (server) */ \ { \ - 0x050C, ZAP_ATTRIBUTE_INDEX(320), 4, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050C, ZAP_ATTRIBUTE_INDEX(321), 4, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Application Launcher (server) */ \ { \ - 0x050D, ZAP_ATTRIBUTE_INDEX(324), 8, 105, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050D, ZAP_ATTRIBUTE_INDEX(325), 8, 105, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Application Basic (server) */ \ { \ - 0x050E, ZAP_ATTRIBUTE_INDEX(332), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050E, ZAP_ATTRIBUTE_INDEX(333), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Account Login (server) */ \ { \ - 0x050F, ZAP_ATTRIBUTE_INDEX(333), 23, 2589, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050F, ZAP_ATTRIBUTE_INDEX(334), 23, 2589, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Test Cluster (server) */ \ { \ - 0x0B04, ZAP_ATTRIBUTE_INDEX(356), 12, 28, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0B04, ZAP_ATTRIBUTE_INDEX(357), 12, 28, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Electrical Measurement (server) */ \ { \ - 0xF000, ZAP_ATTRIBUTE_INDEX(368), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0xF000, ZAP_ATTRIBUTE_INDEX(369), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Binding (server) */ \ { 0x0006, \ - ZAP_ATTRIBUTE_INDEX(369), \ + ZAP_ATTRIBUTE_INDEX(370), \ 7, \ 13, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOnOffServer }, /* Endpoint: 2, Cluster: On/off (server) */ \ { 0x0406, \ - ZAP_ATTRIBUTE_INDEX(376), \ + ZAP_ATTRIBUTE_INDEX(377), \ 4, \ 5, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ @@ -2715,7 +2721,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 15, 3562 }, { ZAP_CLUSTER_INDEX(15), 37, 7259 }, { ZAP_CLUSTER_INDEX(52), 2, 18 }, \ + { ZAP_CLUSTER_INDEX(0), 16, 3564 }, { ZAP_CLUSTER_INDEX(16), 37, 7259 }, { ZAP_CLUSTER_INDEX(53), 2, 18 }, \ } // Largest attribute size is needed for various buffers @@ -2725,7 +2731,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (1497) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (10839) +#define ATTRIBUTE_MAX_SIZE (10841) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (3) @@ -2769,7 +2775,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (211) +#define EMBER_AF_GENERATED_COMMAND_COUNT (214) #define GENERATED_COMMANDS \ { \ \ @@ -2829,6 +2835,11 @@ /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { 0x0037, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetCounts */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0x003C, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenCommissioningWindow */ \ + { 0x003C, 0x01, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenBasicCommissioningWindow */ \ + { 0x003C, 0x02, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RevokeCommissioning */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x003E, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* SetFabric */ \ { 0x003E, 0x01, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* SetFabricResponse */ \ diff --git a/examples/all-clusters-app/all-clusters-common/gen/gen_config.h b/examples/all-clusters-app/all-clusters-common/gen/gen_config.h index 0845ec7ff22bab..578bc13ec9fa7a 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/gen_config.h +++ b/examples/all-clusters-app/all-clusters-common/gen/gen_config.h @@ -30,6 +30,7 @@ /**** Cluster endpoint counts ****/ #define EMBER_AF_ACCOUNT_LOGIN_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_APPLICATION_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_APPLICATION_LAUNCHER_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_AUDIO_OUTPUT_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -86,6 +87,11 @@ #define EMBER_AF_PLUGIN_ACCOUNT_LOGIN_SERVER #define EMBER_AF_PLUGIN_ACCOUNT_LOGIN +// Use this macro to check if the server side of the AdministratorCommissioning cluster is included +#define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING + // Use this macro to check if the server side of the Application Basic cluster is included #define ZCL_USING_APPLICATION_BASIC_CLUSTER_SERVER #define EMBER_AF_PLUGIN_APPLICATION_BASIC_SERVER diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index b71889eac984e4..1ac5b3a912cbe9 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -31,6 +31,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/common/gen/attributes" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/test-cluster-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/on-off-server" diff --git a/examples/bridge-app/bridge-common/bridge-app.zap b/examples/bridge-app/bridge-common/bridge-app.zap index 084383b76249e6..74d7c9ce0d6733 100644 --- a/examples/bridge-app/bridge-common/bridge-app.zap +++ b/examples/bridge-app/bridge-common/bridge-app.zap @@ -1,5 +1,5 @@ { - "featureLevel": 35, + "featureLevel": 39, "creator": "zap", "keyValuePairs": [ { @@ -727,16 +727,9 @@ "source": "client", "incoming": 1, "outgoing": 0 - }, - { - "name": "RetrieveLogsResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 } - ] + ], + "attributes": [] }, { "name": "General Diagnostics", @@ -2085,6 +2078,83 @@ } ] }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "Operational Credentials", "code": 62, @@ -2786,7 +2856,7 @@ "commands": [], "attributes": [ { - "name": "on/off", + "name": "OnOff", "code": 0, "mfgCode": null, "side": "server", @@ -3282,4 +3352,4 @@ } ], "log": [] -} +} \ No newline at end of file diff --git a/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp b/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp index af9eb4fcc9057c..bdc31a3dccf42f 100644 --- a/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp +++ b/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp @@ -51,6 +51,203 @@ void ReportCommandUnsupported(Command * aCommandObj, EndpointId aEndpointId, Clu namespace clusters { +namespace AdministratorCommissioning { + +void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, + TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case Clusters::AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow: { + expectArgumentCount = 1; + uint16_t CommissioningTimeout; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(aEndpointId, apCommandObj, + CommissioningTimeout); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow: { + expectArgumentCount = 6; + uint16_t CommissioningTimeout; + chip::ByteSpan PAKEVerifier; + uint16_t Discriminator; + uint32_t Iterations; + chip::ByteSpan Salt; + uint16_t PasscodeID; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + PAKEVerifier = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: + TLVUnpackError = aDataTlv.Get(Discriminator); + break; + case 3: + TLVUnpackError = aDataTlv.Get(Iterations); + break; + case 4: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + Salt = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 5: + TLVUnpackError = aDataTlv.Get(PasscodeID); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( + aEndpointId, apCommandObj, CommissioningTimeout, PAKEVerifier, Discriminator, Iterations, Salt, PasscodeID); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::RevokeCommissioning: { + + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(aEndpointId, apCommandObj); + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::AdministratorCommissioning::Id, aCommandId); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + Clusters::AdministratorCommissioning::Id, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT + ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError), + ChipError::FormatError(TLVUnpackError), currentDecodeTagId); + // A command with no arguments would never write currentDecodeTagId. If + // progress logging is also disabled, it would look unused. Silence that + // warning. + UNUSED_VAR(currentDecodeTagId); + } +} + +} // namespace AdministratorCommissioning + namespace DiagnosticLogs { void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, @@ -2141,6 +2338,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case Clusters::AdministratorCommissioning::Id: + clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case Clusters::DiagnosticLogs::Id: clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/bridge-app/bridge-common/gen/callback-stub.cpp b/examples/bridge-app/bridge-common/gen/callback-stub.cpp index 98f6b705d15b18..ec0d3067e47ae4 100644 --- a/examples/bridge-app/bridge-common/gen/callback-stub.cpp +++ b/examples/bridge-app/bridge-common/gen/callback-stub.cpp @@ -28,6 +28,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) { switch (clusterId) { + case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID: + emberAfAdministratorCommissioningClusterInitCallback(endpoint); + break; case ZCL_BASIC_CLUSTER_ID: emberAfBasicClusterInitCallback(endpoint); break; @@ -76,6 +79,11 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) } } +void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/bridge-app/bridge-common/gen/endpoint_config.h b/examples/bridge-app/bridge-common/gen/endpoint_config.h index 579ad696654884..d4c982f93add97 100644 --- a/examples/bridge-app/bridge-common/gen/endpoint_config.h +++ b/examples/bridge-app/bridge-common/gen/endpoint_config.h @@ -751,7 +751,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 107 +#define GENERATED_ATTRIBUTE_COUNT 108 #define GENERATED_ATTRIBUTES \ { \ \ @@ -876,6 +876,9 @@ { 0x0006, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(2280) }, /* OverrunCount */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0001, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(2288) }, /* fabrics list */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ @@ -909,7 +912,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 14 +#define GENERATED_CLUSTER_COUNT 15 #define GENERATED_CLUSTERS \ { \ { \ @@ -946,22 +949,25 @@ 0x0037, ZAP_ATTRIBUTE_INDEX(93), 6, 42, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { \ - 0x003E, ZAP_ATTRIBUTE_INDEX(99), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x003C, ZAP_ATTRIBUTE_INDEX(99), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { \ + 0x003E, ZAP_ATTRIBUTE_INDEX(100), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0006, \ - ZAP_ATTRIBUTE_INDEX(101), \ + ZAP_ATTRIBUTE_INDEX(102), \ 2, \ 3, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOnOffServer }, /* Endpoint: 1, Cluster: On/off (server) */ \ { 0x0008, \ - ZAP_ATTRIBUTE_INDEX(103), \ + ZAP_ATTRIBUTE_INDEX(104), \ 2, \ 3, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayLevelControlServer }, /* Endpoint: 1, Cluster: Level Control (server) */ \ { \ - 0x0040, ZAP_ATTRIBUTE_INDEX(105), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0040, ZAP_ATTRIBUTE_INDEX(106), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Fixed Label (server) */ \ } @@ -970,7 +976,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 11, 2604 }, { ZAP_CLUSTER_INDEX(11), 3, 262 }, \ + { ZAP_CLUSTER_INDEX(0), 12, 2606 }, { ZAP_CLUSTER_INDEX(12), 3, 262 }, \ } // Largest attribute size is needed for various buffers @@ -980,7 +986,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (240) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (2866) +#define ATTRIBUTE_MAX_SIZE (2868) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (2) @@ -1024,7 +1030,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (51) +#define EMBER_AF_GENERATED_COMMAND_COUNT (54) #define GENERATED_COMMANDS \ { \ \ @@ -1069,6 +1075,11 @@ /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { 0x0037, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetCounts */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0x003C, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenCommissioningWindow */ \ + { 0x003C, 0x01, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenBasicCommissioningWindow */ \ + { 0x003C, 0x02, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RevokeCommissioning */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x003E, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* SetFabric */ \ { 0x003E, 0x01, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* SetFabricResponse */ \ diff --git a/examples/bridge-app/bridge-common/gen/gen_config.h b/examples/bridge-app/bridge-common/gen/gen_config.h index 7e251038648187..89ad9fb4d1ab1f 100644 --- a/examples/bridge-app/bridge-common/gen/gen_config.h +++ b/examples/bridge-app/bridge-common/gen/gen_config.h @@ -29,6 +29,7 @@ #define EMBER_APS_UNICAST_MESSAGE_COUNT 10 /**** Cluster endpoint counts ****/ +#define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_DESCRIPTOR_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -46,6 +47,11 @@ /**** Cluster Plugins ****/ +// Use this macro to check if the server side of the AdministratorCommissioning cluster is included +#define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING + // Use this macro to check if the server side of the Basic cluster is included #define ZCL_USING_BASIC_CLUSTER_SERVER #define EMBER_AF_PLUGIN_BASIC_SERVER diff --git a/examples/chip-tool/commands/clusters/Commands.h b/examples/chip-tool/commands/clusters/Commands.h index 8242bfbd900eac..458bde1dc1c13d 100644 --- a/examples/chip-tool/commands/clusters/Commands.h +++ b/examples/chip-tool/commands/clusters/Commands.h @@ -1097,6 +1097,7 @@ static void OnThreadNetworkDiagnosticsActiveNetworkFaultsListListAttributeRespon | Cluster Name | ID | |---------------------------------------------------------------------+--------| | AccountLogin | 0x050E | +| AdministratorCommissioning | 0x003C | | ApplicationBasic | 0x050D | | ApplicationLauncher | 0x050C | | AudioOutput | 0x050B | @@ -1147,6 +1148,7 @@ static void OnThreadNetworkDiagnosticsActiveNetworkFaultsListListAttributeRespon \*----------------------------------------------------------------------------*/ constexpr chip::ClusterId kAccountLoginClusterId = 0x050E; +constexpr chip::ClusterId kAdministratorCommissioningClusterId = 0x003C; constexpr chip::ClusterId kApplicationBasicClusterId = 0x050D; constexpr chip::ClusterId kApplicationLauncherClusterId = 0x050C; constexpr chip::ClusterId kAudioOutputClusterId = 0x050B; @@ -1344,6 +1346,191 @@ class ReadAccountLoginClusterRevision : public ModelCommand new chip::Callback::Callback(OnDefaultFailureResponse, this); }; +/*----------------------------------------------------------------------------*\ +| Cluster AdministratorCommissioning | 0x003C | +|------------------------------------------------------------------------------| +| Commands: | | +| * OpenBasicCommissioningWindow | 0x01 | +| * OpenCommissioningWindow | 0x00 | +| * RevokeCommissioning | 0x02 | +|------------------------------------------------------------------------------| +| Attributes: | | +| * ClusterRevision | 0xFFFD | +\*----------------------------------------------------------------------------*/ + +/* + * Command OpenBasicCommissioningWindow + */ +class AdministratorCommissioningOpenBasicCommissioningWindow : public ModelCommand +{ +public: + AdministratorCommissioningOpenBasicCommissioningWindow() : ModelCommand("open-basic-commissioning-window") + { + AddArgument("CommissioningTimeout", 0, UINT16_MAX, &mCommissioningTimeout); + ModelCommand::AddArguments(); + } + ~AdministratorCommissioningOpenBasicCommissioningWindow() + { + delete onSuccessCallback; + delete onFailureCallback; + } + + CHIP_ERROR SendCommand(ChipDevice * device, uint8_t endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x003C) command (0x01) on endpoint %" PRIu8, endpointId); + + chip::Controller::AdministratorCommissioningCluster cluster; + cluster.Associate(device, endpointId); + return cluster.OpenBasicCommissioningWindow(onSuccessCallback->Cancel(), onFailureCallback->Cancel(), + mCommissioningTimeout); + } + +private: + chip::Callback::Callback * onSuccessCallback = + new chip::Callback::Callback(OnDefaultSuccessResponse, this); + chip::Callback::Callback * onFailureCallback = + new chip::Callback::Callback(OnDefaultFailureResponse, this); + uint16_t mCommissioningTimeout; +}; + +/* + * Command OpenCommissioningWindow + */ +class AdministratorCommissioningOpenCommissioningWindow : public ModelCommand +{ +public: + AdministratorCommissioningOpenCommissioningWindow() : ModelCommand("open-commissioning-window") + { + AddArgument("CommissioningTimeout", 0, UINT16_MAX, &mCommissioningTimeout); + AddArgument("PAKEVerifier", &mPAKEVerifier); + AddArgument("Discriminator", 0, UINT16_MAX, &mDiscriminator); + AddArgument("Iterations", 0, UINT32_MAX, &mIterations); + AddArgument("Salt", &mSalt); + AddArgument("PasscodeID", 0, UINT16_MAX, &mPasscodeID); + ModelCommand::AddArguments(); + } + ~AdministratorCommissioningOpenCommissioningWindow() + { + delete onSuccessCallback; + delete onFailureCallback; + } + + CHIP_ERROR SendCommand(ChipDevice * device, uint8_t endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x003C) command (0x00) on endpoint %" PRIu8, endpointId); + + chip::Controller::AdministratorCommissioningCluster cluster; + cluster.Associate(device, endpointId); + return cluster.OpenCommissioningWindow(onSuccessCallback->Cancel(), onFailureCallback->Cancel(), mCommissioningTimeout, + mPAKEVerifier, mDiscriminator, mIterations, mSalt, mPasscodeID); + } + +private: + chip::Callback::Callback * onSuccessCallback = + new chip::Callback::Callback(OnDefaultSuccessResponse, this); + chip::Callback::Callback * onFailureCallback = + new chip::Callback::Callback(OnDefaultFailureResponse, this); + uint16_t mCommissioningTimeout; + chip::ByteSpan mPAKEVerifier; + uint16_t mDiscriminator; + uint32_t mIterations; + chip::ByteSpan mSalt; + uint16_t mPasscodeID; +}; + +/* + * Command RevokeCommissioning + */ +class AdministratorCommissioningRevokeCommissioning : public ModelCommand +{ +public: + AdministratorCommissioningRevokeCommissioning() : ModelCommand("revoke-commissioning") { ModelCommand::AddArguments(); } + ~AdministratorCommissioningRevokeCommissioning() + { + delete onSuccessCallback; + delete onFailureCallback; + } + + CHIP_ERROR SendCommand(ChipDevice * device, uint8_t endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x003C) command (0x02) on endpoint %" PRIu8, endpointId); + + chip::Controller::AdministratorCommissioningCluster cluster; + cluster.Associate(device, endpointId); + return cluster.RevokeCommissioning(onSuccessCallback->Cancel(), onFailureCallback->Cancel()); + } + +private: + chip::Callback::Callback * onSuccessCallback = + new chip::Callback::Callback(OnDefaultSuccessResponse, this); + chip::Callback::Callback * onFailureCallback = + new chip::Callback::Callback(OnDefaultFailureResponse, this); +}; + +/* + * Discover Attributes + */ +class DiscoverAdministratorCommissioningAttributes : public ModelCommand +{ +public: + DiscoverAdministratorCommissioningAttributes() : ModelCommand("discover") { ModelCommand::AddArguments(); } + + ~DiscoverAdministratorCommissioningAttributes() + { + delete onSuccessCallback; + delete onFailureCallback; + } + + CHIP_ERROR SendCommand(ChipDevice * device, uint8_t endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x0000) command (0x0C) on endpoint %" PRIu8, endpointId); + + chip::Controller::AdministratorCommissioningCluster cluster; + cluster.Associate(device, endpointId); + return cluster.DiscoverAttributes(onSuccessCallback->Cancel(), onFailureCallback->Cancel()); + } + +private: + chip::Callback::Callback * onSuccessCallback = + new chip::Callback::Callback(OnDefaultSuccessResponse, this); + chip::Callback::Callback * onFailureCallback = + new chip::Callback::Callback(OnDefaultFailureResponse, this); +}; + +/* + * Attribute ClusterRevision + */ +class ReadAdministratorCommissioningClusterRevision : public ModelCommand +{ +public: + ReadAdministratorCommissioningClusterRevision() : ModelCommand("read") + { + AddArgument("attr-name", "cluster-revision"); + ModelCommand::AddArguments(); + } + + ~ReadAdministratorCommissioningClusterRevision() + { + delete onSuccessCallback; + delete onFailureCallback; + } + + CHIP_ERROR SendCommand(ChipDevice * device, uint8_t endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x003C) command (0x00) on endpoint %" PRIu8, endpointId); + + chip::Controller::AdministratorCommissioningCluster cluster; + cluster.Associate(device, endpointId); + return cluster.ReadAttributeClusterRevision(onSuccessCallback->Cancel(), onFailureCallback->Cancel()); + } + +private: + chip::Callback::Callback * onSuccessCallback = + new chip::Callback::Callback(OnInt16uAttributeResponse, this); + chip::Callback::Callback * onFailureCallback = + new chip::Callback::Callback(OnDefaultFailureResponse, this); +}; + /*----------------------------------------------------------------------------*\ | Cluster ApplicationBasic | 0x050D | |------------------------------------------------------------------------------| @@ -23492,6 +23679,20 @@ void registerClusterAccountLogin(Commands & commands) commands.Register(clusterName, clusterCommands); } +void registerClusterAdministratorCommissioning(Commands & commands) +{ + const char * clusterName = "AdministratorCommissioning"; + + commands_list clusterCommands = { + make_unique(), // + make_unique(), // + make_unique(), // + make_unique(), // + make_unique(), // + }; + + commands.Register(clusterName, clusterCommands); +} void registerClusterApplicationBasic(Commands & commands) { const char * clusterName = "ApplicationBasic"; @@ -24532,6 +24733,7 @@ void registerClusterWindowCovering(Commands & commands) void registerClusters(Commands & commands) { registerClusterAccountLogin(commands); + registerClusterAdministratorCommissioning(commands); registerClusterApplicationBasic(commands); registerClusterApplicationLauncher(commands); registerClusterAudioOutput(commands); diff --git a/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp b/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp index 73a118fe3a3109..d8deb24f2f8bbf 100644 --- a/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp +++ b/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp @@ -51,6 +51,203 @@ void ReportCommandUnsupported(Command * aCommandObj, EndpointId aEndpointId, Clu namespace clusters { +namespace AdministratorCommissioning { + +void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, + TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case Clusters::AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow: { + expectArgumentCount = 1; + uint16_t CommissioningTimeout; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(aEndpointId, apCommandObj, + CommissioningTimeout); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow: { + expectArgumentCount = 6; + uint16_t CommissioningTimeout; + chip::ByteSpan PAKEVerifier; + uint16_t Discriminator; + uint32_t Iterations; + chip::ByteSpan Salt; + uint16_t PasscodeID; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + PAKEVerifier = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: + TLVUnpackError = aDataTlv.Get(Discriminator); + break; + case 3: + TLVUnpackError = aDataTlv.Get(Iterations); + break; + case 4: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + Salt = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 5: + TLVUnpackError = aDataTlv.Get(PasscodeID); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( + aEndpointId, apCommandObj, CommissioningTimeout, PAKEVerifier, Discriminator, Iterations, Salt, PasscodeID); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::RevokeCommissioning: { + + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(aEndpointId, apCommandObj); + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::AdministratorCommissioning::Id, aCommandId); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + Clusters::AdministratorCommissioning::Id, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT + ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError), + ChipError::FormatError(TLVUnpackError), currentDecodeTagId); + // A command with no arguments would never write currentDecodeTagId. If + // progress logging is also disabled, it would look unused. Silence that + // warning. + UNUSED_VAR(currentDecodeTagId); + } +} + +} // namespace AdministratorCommissioning + namespace ColorControl { void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, @@ -3812,6 +4009,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case Clusters::AdministratorCommissioning::Id: + clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case Clusters::ColorControl::Id: clusters::ColorControl::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/lighting-app/lighting-common/gen/callback-stub.cpp b/examples/lighting-app/lighting-common/gen/callback-stub.cpp index acba1cc98d6df6..98c9af9be12156 100644 --- a/examples/lighting-app/lighting-common/gen/callback-stub.cpp +++ b/examples/lighting-app/lighting-common/gen/callback-stub.cpp @@ -28,6 +28,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) { switch (clusterId) { + case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID: + emberAfAdministratorCommissioningClusterInitCallback(endpoint); + break; case ZCL_BASIC_CLUSTER_ID: emberAfBasicClusterInitCallback(endpoint); break; @@ -76,6 +79,11 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) } } +void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/lighting-app/lighting-common/gen/endpoint_config.h b/examples/lighting-app/lighting-common/gen/endpoint_config.h index 1aa34a02a29159..e9060bbdb63c04 100644 --- a/examples/lighting-app/lighting-common/gen/endpoint_config.h +++ b/examples/lighting-app/lighting-common/gen/endpoint_config.h @@ -649,7 +649,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 140 +#define GENERATED_ATTRIBUTE_COUNT 141 #define GENERATED_ATTRIBUTES \ { \ \ @@ -776,6 +776,9 @@ { 0x0006, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1664) }, /* OverrunCount */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0001, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(1672) }, /* fabrics list */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ @@ -849,7 +852,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 14 +#define GENERATED_CLUSTER_COUNT 15 #define GENERATED_CLUSTERS \ { \ { 0x0028, \ @@ -883,28 +886,31 @@ 0x0037, ZAP_ATTRIBUTE_INDEX(95), 6, 42, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { \ - 0x003E, ZAP_ATTRIBUTE_INDEX(101), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x003C, ZAP_ATTRIBUTE_INDEX(101), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { \ + 0x003E, ZAP_ATTRIBUTE_INDEX(102), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0006, \ - ZAP_ATTRIBUTE_INDEX(103), \ + ZAP_ATTRIBUTE_INDEX(104), \ 6, \ 9, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOnOffServer }, /* Endpoint: 1, Cluster: On/off (server) */ \ { 0x0008, \ - ZAP_ATTRIBUTE_INDEX(109), \ + ZAP_ATTRIBUTE_INDEX(110), \ 5, \ 7, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayLevelControlServer }, /* Endpoint: 1, Cluster: Level Control (server) */ \ { 0x0300, \ - ZAP_ATTRIBUTE_INDEX(114), \ + ZAP_ATTRIBUTE_INDEX(115), \ 22, \ 36, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayColorControlServer }, /* Endpoint: 1, Cluster: Color Control (server) */ \ { 0x0406, \ - ZAP_ATTRIBUTE_INDEX(136), \ + ZAP_ATTRIBUTE_INDEX(137), \ 4, \ 5, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ @@ -916,7 +922,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 10, 1988 }, { ZAP_CLUSTER_INDEX(10), 4, 57 }, \ + { ZAP_CLUSTER_INDEX(0), 11, 1990 }, { ZAP_CLUSTER_INDEX(11), 4, 57 }, \ } // Largest attribute size is needed for various buffers @@ -926,7 +932,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (642) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (2045) +#define ATTRIBUTE_MAX_SIZE (2047) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (2) @@ -970,7 +976,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (75) +#define EMBER_AF_GENERATED_COMMAND_COUNT (78) #define GENERATED_COMMANDS \ { \ \ @@ -1021,6 +1027,11 @@ /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { 0x0037, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetCounts */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0x003C, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenCommissioningWindow */ \ + { 0x003C, 0x01, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenBasicCommissioningWindow */ \ + { 0x003C, 0x02, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RevokeCommissioning */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x003E, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* SetFabric */ \ { 0x003E, 0x01, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* SetFabricResponse */ \ diff --git a/examples/lighting-app/lighting-common/gen/gen_config.h b/examples/lighting-app/lighting-common/gen/gen_config.h index f0ef37c275eec4..dcda6268547d37 100644 --- a/examples/lighting-app/lighting-common/gen/gen_config.h +++ b/examples/lighting-app/lighting-common/gen/gen_config.h @@ -29,6 +29,7 @@ #define EMBER_APS_UNICAST_MESSAGE_COUNT 10 /**** Cluster endpoint counts ****/ +#define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_COLOR_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -46,6 +47,11 @@ /**** Cluster Plugins ****/ +// Use this macro to check if the server side of the AdministratorCommissioning cluster is included +#define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING + // Use this macro to check if the server side of the Basic cluster is included #define ZCL_USING_BASIC_CLUSTER_SERVER #define EMBER_AF_PLUGIN_BASIC_SERVER diff --git a/examples/lighting-app/lighting-common/lighting-app.zap b/examples/lighting-app/lighting-common/lighting-app.zap index 71dd08dd22ee07..b21d40e0aa9877 100644 --- a/examples/lighting-app/lighting-common/lighting-app.zap +++ b/examples/lighting-app/lighting-common/lighting-app.zap @@ -2896,6 +2896,83 @@ } ] }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "Operational Credentials", "code": 62, diff --git a/examples/lighting-app/mbed/CMakeLists.txt b/examples/lighting-app/mbed/CMakeLists.txt index ce73823fab027d..a915939a383482 100644 --- a/examples/lighting-app/mbed/CMakeLists.txt +++ b/examples/lighting-app/mbed/CMakeLists.txt @@ -74,6 +74,7 @@ target_sources(${APP_TARGET} PRIVATE ${CHIP_ROOT}/src/app/server/RendezvousServer.cpp ${CHIP_ROOT}/src/app/server/Server.cpp ${CHIP_ROOT}/src/app/server/StorablePeerConnection.cpp + ${CHIP_ROOT}/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp ${CHIP_ROOT}/src/app/clusters/basic/basic.cpp ${CHIP_ROOT}/src/app/clusters/bindings/bindings.cpp ${CHIP_ROOT}/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp diff --git a/examples/lighting-app/nrfconnect/CMakeLists.txt b/examples/lighting-app/nrfconnect/CMakeLists.txt index 4f9795adcfdbdc..e30cc041c2df2c 100644 --- a/examples/lighting-app/nrfconnect/CMakeLists.txt +++ b/examples/lighting-app/nrfconnect/CMakeLists.txt @@ -87,6 +87,7 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/server/RendezvousServer.cpp ${CHIP_ROOT}/src/app/server/Server.cpp ${CHIP_ROOT}/src/app/server/StorablePeerConnection.cpp + ${CHIP_ROOT}/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp ${CHIP_ROOT}/src/app/clusters/basic/basic.cpp ${CHIP_ROOT}/src/app/clusters/bindings/bindings.cpp ${CHIP_ROOT}/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp diff --git a/examples/lighting-app/telink/CMakeLists.txt b/examples/lighting-app/telink/CMakeLists.txt index 369ecfb6eee390..6fb81995dc8317 100644 --- a/examples/lighting-app/telink/CMakeLists.txt +++ b/examples/lighting-app/telink/CMakeLists.txt @@ -77,6 +77,7 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/server/RendezvousServer.cpp ${CHIP_ROOT}/src/app/server/Server.cpp ${CHIP_ROOT}/src/app/server/StorablePeerConnection.cpp + ${CHIP_ROOT}/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp ${CHIP_ROOT}/src/app/clusters/basic/basic.cpp ${CHIP_ROOT}/src/app/clusters/bindings/bindings.cpp ${CHIP_ROOT}/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp diff --git a/examples/lock-app/esp32/main/CMakeLists.txt b/examples/lock-app/esp32/main/CMakeLists.txt index e0f24c53474de7..9e82d40343d48c 100644 --- a/examples/lock-app/esp32/main/CMakeLists.txt +++ b/examples/lock-app/esp32/main/CMakeLists.txt @@ -38,6 +38,7 @@ idf_component_register(INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" diff --git a/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp b/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp index 21aff33d69ee42..fe910c7ff2caef 100644 --- a/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp +++ b/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp @@ -51,6 +51,203 @@ void ReportCommandUnsupported(Command * aCommandObj, EndpointId aEndpointId, Clu namespace clusters { +namespace AdministratorCommissioning { + +void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, + TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case Clusters::AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow: { + expectArgumentCount = 1; + uint16_t CommissioningTimeout; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(aEndpointId, apCommandObj, + CommissioningTimeout); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow: { + expectArgumentCount = 6; + uint16_t CommissioningTimeout; + chip::ByteSpan PAKEVerifier; + uint16_t Discriminator; + uint32_t Iterations; + chip::ByteSpan Salt; + uint16_t PasscodeID; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + PAKEVerifier = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: + TLVUnpackError = aDataTlv.Get(Discriminator); + break; + case 3: + TLVUnpackError = aDataTlv.Get(Iterations); + break; + case 4: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + Salt = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 5: + TLVUnpackError = aDataTlv.Get(PasscodeID); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( + aEndpointId, apCommandObj, CommissioningTimeout, PAKEVerifier, Discriminator, Iterations, Salt, PasscodeID); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::RevokeCommissioning: { + + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(aEndpointId, apCommandObj); + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::AdministratorCommissioning::Id, aCommandId); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + Clusters::AdministratorCommissioning::Id, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT + ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError), + ChipError::FormatError(TLVUnpackError), currentDecodeTagId); + // A command with no arguments would never write currentDecodeTagId. If + // progress logging is also disabled, it would look unused. Silence that + // warning. + UNUSED_VAR(currentDecodeTagId); + } +} + +} // namespace AdministratorCommissioning + namespace DiagnosticLogs { void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, @@ -1617,6 +1814,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case Clusters::AdministratorCommissioning::Id: + clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case Clusters::DiagnosticLogs::Id: clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/lock-app/lock-common/gen/callback-stub.cpp b/examples/lock-app/lock-common/gen/callback-stub.cpp index b18b35167f3e40..9a196a3d69a8d0 100644 --- a/examples/lock-app/lock-common/gen/callback-stub.cpp +++ b/examples/lock-app/lock-common/gen/callback-stub.cpp @@ -28,6 +28,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) { switch (clusterId) { + case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID: + emberAfAdministratorCommissioningClusterInitCallback(endpoint); + break; case ZCL_BASIC_CLUSTER_ID: emberAfBasicClusterInitCallback(endpoint); break; @@ -67,6 +70,11 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) } } +void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/lock-app/lock-common/gen/endpoint_config.h b/examples/lock-app/lock-common/gen/endpoint_config.h index 7810e6c16b0380..d7ea443a76c91d 100644 --- a/examples/lock-app/lock-common/gen/endpoint_config.h +++ b/examples/lock-app/lock-common/gen/endpoint_config.h @@ -583,7 +583,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 98 +#define GENERATED_ATTRIBUTE_COUNT 99 #define GENERATED_ATTRIBUTES \ { \ \ @@ -701,6 +701,9 @@ { 0x0006, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1264) }, /* OverrunCount */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0001, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(1272) }, /* fabrics list */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ @@ -723,7 +726,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 11 +#define GENERATED_CLUSTER_COUNT 12 #define GENERATED_CLUSTERS \ { \ { 0x0028, \ @@ -757,10 +760,13 @@ 0x0037, ZAP_ATTRIBUTE_INDEX(88), 6, 42, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { \ - 0x003E, ZAP_ATTRIBUTE_INDEX(94), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x003C, ZAP_ATTRIBUTE_INDEX(94), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { \ + 0x003E, ZAP_ATTRIBUTE_INDEX(95), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0006, \ - ZAP_ATTRIBUTE_INDEX(96), \ + ZAP_ATTRIBUTE_INDEX(97), \ 2, \ 3, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ @@ -772,7 +778,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 10, 1586 }, { ZAP_CLUSTER_INDEX(10), 1, 3 }, \ + { ZAP_CLUSTER_INDEX(0), 11, 1588 }, { ZAP_CLUSTER_INDEX(11), 1, 3 }, \ } // Largest attribute size is needed for various buffers @@ -782,7 +788,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (240) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (1589) +#define ATTRIBUTE_MAX_SIZE (1591) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (2) @@ -826,7 +832,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (43) +#define EMBER_AF_GENERATED_COMMAND_COUNT (46) #define GENERATED_COMMANDS \ { \ \ @@ -871,6 +877,11 @@ /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { 0x0037, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetCounts */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0x003C, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenCommissioningWindow */ \ + { 0x003C, 0x01, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenBasicCommissioningWindow */ \ + { 0x003C, 0x02, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RevokeCommissioning */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x003E, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* SetFabric */ \ { 0x003E, 0x01, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* SetFabricResponse */ \ diff --git a/examples/lock-app/lock-common/gen/gen_config.h b/examples/lock-app/lock-common/gen/gen_config.h index 32a444f467558e..4b89a47f65bdcf 100644 --- a/examples/lock-app/lock-common/gen/gen_config.h +++ b/examples/lock-app/lock-common/gen/gen_config.h @@ -29,6 +29,7 @@ #define EMBER_APS_UNICAST_MESSAGE_COUNT 10 /**** Cluster endpoint counts ****/ +#define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -43,6 +44,11 @@ /**** Cluster Plugins ****/ +// Use this macro to check if the server side of the AdministratorCommissioning cluster is included +#define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING + // Use this macro to check if the server side of the Basic cluster is included #define ZCL_USING_BASIC_CLUSTER_SERVER #define EMBER_AF_PLUGIN_BASIC_SERVER diff --git a/examples/lock-app/lock-common/lock-app.zap b/examples/lock-app/lock-common/lock-app.zap index e5551b3feba3ea..d61db9550fdf48 100644 --- a/examples/lock-app/lock-common/lock-app.zap +++ b/examples/lock-app/lock-common/lock-app.zap @@ -1,5 +1,5 @@ { - "featureLevel": 35, + "featureLevel": 45, "creator": "zap", "keyValuePairs": [ { @@ -32,9 +32,9 @@ "endpointTypes": [ { "name": "Anonymous Endpoint Type", - "deviceTypeName": "CBA-onofflight", - "deviceTypeCode": 256, - "deviceTypeProfileId": 265, + "deviceTypeName": null, + "deviceTypeCode": null, + "deviceTypeProfileId": null, "clusters": [ { "name": "Power Configuration", @@ -721,7 +721,7 @@ "commands": [], "attributes": [ { - "name": "on/off", + "name": "OnOff", "code": 0, "mfgCode": null, "side": "server", @@ -831,30 +831,13 @@ ] }, { - "name": "Commissioning", - "code": 21, + "name": "Basic", + "code": 40, "mfgCode": null, - "define": "COMMISSIONING_CLUSTER", + "define": "BASIC_CLUSTER", "side": "client", "enabled": 0, - "commands": [ - { - "name": "RestartDevice", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "ResetStartupParameters", - "code": 3, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - } - ], + "commands": [], "attributes": [ { "name": "cluster revision", @@ -863,9 +846,9 @@ "side": "client", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -874,335 +857,324 @@ ] }, { - "name": "Commissioning", - "code": 21, + "name": "Basic", + "code": 40, "mfgCode": null, - "define": "COMMISSIONING_CLUSTER", + "define": "BASIC_CLUSTER", "side": "server", - "enabled": 0, + "enabled": 1, "commands": [ { - "name": "RestartDeviceResponse", + "name": "StartUp", "code": 0, "mfgCode": null, "source": "server", - "incoming": 0, + "incoming": 1, "outgoing": 1 }, { - "name": "SaveStartupParametersResponse", + "name": "ShutDown", "code": 1, "mfgCode": null, "source": "server", - "incoming": 0, + "incoming": 1, "outgoing": 1 }, { - "name": "RestoreStartupParametersResponse", + "name": "Leave", "code": 2, "mfgCode": null, "source": "server", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "ResetStartupParametersResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "incoming": 0, + "incoming": 1, "outgoing": 1 } ], "attributes": [ { - "name": "short address", + "name": "InteractionModelVersion", "code": 0, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0xFFFF", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "extended pan id", + "name": "VendorName", "code": 1, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0xFFFFFFFFFFFFFFFF", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "pan id", + "name": "VendorID", "code": 2, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0xFFFF", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "channel mask", + "name": "ProductName", "code": 3, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x07FFF800", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "protocol version", + "name": "ProductID", "code": 4, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x02", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "stack profile", + "name": "UserLabel", "code": 5, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x02", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "startup control", + "name": "Location", "code": 6, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x03", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "trust center address", - "code": 16, + "name": "HardwareVersion", + "code": 7, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": "0x00", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "network key", - "code": 18, + "name": "HardwareVersionString", + "code": 8, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x00000000000000000000000000000000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "use insecure join", - "code": 19, + "name": "SoftwareVersion", + "code": 9, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x01", + "defaultValue": "0x00", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "preconfigured link key", - "code": 20, + "name": "SoftwareVersionString", + "code": 10, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x00000000000000000000000000000000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "network key sequence number", - "code": 21, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "3", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ { - "name": "network key type", - "code": 22, + "name": "ArmFailSafe", + "code": 0, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x05", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "network manager address", - "code": 23, + "name": "SetRegulatoryConfig", + "code": 2, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 0 }, { - "name": "scan attempts", - "code": 32, + "name": "CommissioningComplete", + "code": 4, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x05", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ { - "name": "time between scans", - "code": 33, + "name": "cluster revision", + "code": 65533, "mfgCode": null, - "side": "server", + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0064", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ { - "name": "rejoin interval", - "code": 34, + "name": "ArmFailSafeResponse", + "code": 1, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x003C", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 1, + "outgoing": 1 }, { - "name": "max rejoin interval", - "code": 35, + "name": "SetRegulatoryConfigResponse", + "code": 3, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0E10", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 0, + "outgoing": 1 }, { - "name": "indirect poll rate", - "code": 48, + "name": "CommissioningCompleteResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "FabricId", + "code": 0, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "o", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "parent retry threshold", - "code": 49, + "name": "Breadcrumb", + "code": 1, "mfgCode": null, "side": "server", "included": 1, @@ -1216,1123 +1188,284 @@ "reportableChange": 0 }, { - "name": "concentrator flag", - "code": 64, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ { - "name": "concentrator radius", - "code": 65, + "name": "ScanNetworks", + "code": 0, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0F", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "concentrator discovery time", - "code": 66, + "name": "AddWiFiNetwork", + "code": 2, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x00", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 0 }, { - "name": "cluster revision", - "code": 65533, + "name": "UpdateWiFiNetwork", + "code": 4, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "2", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Basic", - "code": 40, - "mfgCode": null, - "define": "BASIC_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [], - "attributes": [ + "source": "client", + "incoming": 1, + "outgoing": 0 + }, { - "name": "cluster revision", - "code": 65533, + "name": "AddThreadNetwork", + "code": 6, "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "3", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Basic", - "code": 40, - "mfgCode": null, - "define": "BASIC_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ + "source": "client", + "incoming": 1, + "outgoing": 0 + }, { - "name": "StartUp", - "code": 0, + "name": "UpdateThreadNetwork", + "code": 8, "mfgCode": null, - "source": "server", + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RemoveNetwork", + "code": 10, + "mfgCode": null, + "source": "client", "incoming": 1, "outgoing": 1 }, { - "name": "ShutDown", - "code": 1, + "name": "EnableNetwork", + "code": 12, "mfgCode": null, - "source": "server", + "source": "client", "incoming": 1, "outgoing": 1 }, { - "name": "Leave", - "code": 2, + "name": "DisableNetwork", + "code": 14, "mfgCode": null, - "source": "server", + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetLastNetworkCommissioningResult", + "code": 16, + "mfgCode": null, + "source": "client", "incoming": 1, "outgoing": 1 } ], "attributes": [ { - "name": "InteractionModelVersion", - "code": 0, + "name": "cluster revision", + "code": 65533, "mfgCode": null, - "side": "server", + "side": "client", "included": 1, "storageOption": "RAM", - "singleton": 1, + "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ { - "name": "VendorName", + "name": "ScanNetworksResponse", "code": 1, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "VendorID", - "code": 2, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 1, + "outgoing": 1 }, { - "name": "ProductName", + "name": "AddWiFiNetworkResponse", "code": 3, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductID", - "code": 4, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 0, + "outgoing": 1 }, { - "name": "UserLabel", - "code": 5, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "Location", - "code": 6, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "HardwareVersion", - "code": 7, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "0x00", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "HardwareVersionString", - "code": 8, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "SoftwareVersion", - "code": 9, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "0x00", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "SoftwareVersionString", - "code": 10, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "3", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "General Commissioning", - "code": 48, - "mfgCode": null, - "define": "GENERAL_COMMISSIONING_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [ - { - "name": "ArmFailSafe", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "SetRegulatoryConfig", - "code": 2, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "CommissioningComplete", - "code": 4, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - } - ], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "General Commissioning", - "code": 48, - "mfgCode": null, - "define": "GENERAL_COMMISSIONING_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "ArmFailSafeResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "SetRegulatoryConfigResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "CommissioningCompleteResponse", + "name": "UpdateWiFiNetworkResponse", "code": 5, "mfgCode": null, "source": "server", - "incoming": 1, - "outgoing": 1 - } - ], - "attributes": [ - { - "name": "FabricId", - "code": 0, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "o", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "Breadcrumb", - "code": 1, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Network Commissioning", - "code": 49, - "mfgCode": null, - "define": "NETWORK_COMMISSIONING_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [ - { - "name": "ScanNetworks", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "AddWiFiNetwork", - "code": 2, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "UpdateWiFiNetwork", - "code": 4, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "AddThreadNetwork", - "code": 6, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "UpdateThreadNetwork", - "code": 8, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "RemoveNetwork", - "code": 10, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "EnableNetwork", - "code": 12, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "DisableNetwork", - "code": 14, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "GetLastNetworkCommissioningResult", - "code": 16, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - } - ], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Network Commissioning", - "code": 49, - "mfgCode": null, - "define": "NETWORK_COMMISSIONING_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "ScanNetworksResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "AddWiFiNetworkResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "UpdateWiFiNetworkResponse", - "code": 5, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "AddThreadNetworkResponse", - "code": 7, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "UpdateThreadNetworkResponse", - "code": 9, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "RemoveNetworkResponse", - "code": 11, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "EnableNetworkResponse", - "code": 13, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "DisableNetworkResponse", - "code": 15, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - } - ], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Diagnostic Logs", - "code": 50, - "mfgCode": null, - "define": "DIAGNOSTIC_LOGS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "RetrieveLogsRequest", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "RetrieveLogsResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 - } - ] - }, - { - "name": "General Diagnostics", - "code": 51, - "mfgCode": null, - "define": "GENERAL_DIAGNOSTICS_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "General Diagnostics", - "code": 51, - "mfgCode": null, - "define": "GENERAL_DIAGNOSTICS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [], - "attributes": [ - { - "name": "NetworkInterfaces", - "code": 0, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "RebootCount", - "code": 1, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Software Diagnostics", - "code": 52, - "mfgCode": null, - "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [ - { - "name": "ResetWatermarks", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 0, - "outgoing": 1 - } - ], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Software Diagnostics", - "code": 52, - "mfgCode": null, - "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [], - "attributes": [ - { - "name": "CurrentHeapHighWatermark", - "code": 3, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000000000000000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Thread Network Diagnostics", - "code": 53, - "mfgCode": null, - "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Thread Network Diagnostics", - "code": 53, - "mfgCode": null, - "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [], - "attributes": [ - { - "name": "channel", - "code": 0, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "RoutingRole", - "code": 1, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "NetworkName", - "code": 2, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "PanId", - "code": 3, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ExtendedPanId", - "code": 4, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000000000000000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "MeshLocalPrefix", - "code": 5, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "OverrunCount", - "code": 6, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000000000000000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "NeighborTableList", - "code": 7, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "RouteTableList", - "code": 8, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "PartitionId", - "code": 9, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "weighting", - "code": 10, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "incoming": 0, + "outgoing": 1 }, { - "name": "DataVersion", - "code": 11, + "name": "AddThreadNetworkResponse", + "code": 7, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 0, + "outgoing": 1 }, { - "name": "StableDataVersion", - "code": 12, + "name": "UpdateThreadNetworkResponse", + "code": 9, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 0, + "outgoing": 1 }, { - "name": "LeaderRouterId", - "code": 13, + "name": "RemoveNetworkResponse", + "code": 11, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 1, + "outgoing": 1 }, { - "name": "DetachedRoleCount", - "code": 14, + "name": "EnableNetworkResponse", + "code": 13, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 1, + "outgoing": 1 }, { - "name": "ChildRoleCount", + "name": "DisableNetworkResponse", "code": 15, "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ { - "name": "RouterRoleCount", - "code": 16, + "name": "RetrieveLogsRequest", + "code": 0, "mfgCode": null, - "side": "server", + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ { - "name": "LeaderRoleCount", - "code": 17, + "name": "NetworkInterfaces", + "code": 0, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "AttachAttemptCount", - "code": 18, + "name": "RebootCount", + "code": 1, "mfgCode": null, "side": "server", "included": 1, @@ -2346,128 +1479,181 @@ "reportableChange": 0 }, { - "name": "PartitionIdChangeCount", - "code": 19, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ { - "name": "BetterPartitionAttachAttemptCount", - "code": 20, + "name": "ResetWatermarks", + "code": 0, "mfgCode": null, - "side": "server", + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ { - "name": "ParentChangeCount", - "code": 21, + "name": "CurrentHeapHighWatermark", + "code": 3, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "0x0000000000000000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxTotalCount", - "code": 22, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ { - "name": "TxUnicastCount", - "code": 23, + "name": "cluster revision", + "code": 65533, "mfgCode": null, - "side": "server", + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Thread Network Diagnostics", + "code": 53, + "mfgCode": null, + "define": "THREAD_NETWORK_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ { - "name": "TxBroadcastCount", - "code": 24, + "name": "channel", + "code": 0, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxAckRequestedCount", - "code": 25, + "name": "RoutingRole", + "code": 1, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxAckedCount", - "code": 26, + "name": "NetworkName", + "code": 2, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "0", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxNoAckRequestedCount", - "code": 27, + "name": "PanId", + "code": 3, "mfgCode": null, "side": "server", "included": 1, @@ -2481,158 +1667,158 @@ "reportableChange": 0 }, { - "name": "TxDataCount", - "code": 28, + "name": "ExtendedPanId", + "code": 4, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "0x0000000000000000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxDataPollCount", - "code": 29, + "name": "MeshLocalPrefix", + "code": 5, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxBeaconCount", - "code": 30, + "name": "OverrunCount", + "code": 6, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "0x0000000000000000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxBeaconRequestCount", - "code": 31, + "name": "NeighborTableList", + "code": 7, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxOtherCount", - "code": 32, + "name": "RouteTableList", + "code": 8, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxRetryCount", - "code": 33, + "name": "PartitionId", + "code": 9, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxDirectMaxRetryExpiryCount", - "code": 34, + "name": "weighting", + "code": 10, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxIndirectMaxRetryExpiryCount", - "code": 35, + "name": "DataVersion", + "code": 11, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxErrCcaCount", - "code": 36, + "name": "StableDataVersion", + "code": 12, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxErrAbortCount", - "code": 37, + "name": "LeaderRouterId", + "code": 13, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxErrBusyChannelCount", - "code": 38, + "name": "DetachedRoleCount", + "code": 14, "mfgCode": null, "side": "server", "included": 1, @@ -2646,8 +1832,8 @@ "reportableChange": 0 }, { - "name": "RxTotalCount", - "code": 39, + "name": "ChildRoleCount", + "code": 15, "mfgCode": null, "side": "server", "included": 1, @@ -2661,8 +1847,8 @@ "reportableChange": 0 }, { - "name": "RxUnicastCount", - "code": 40, + "name": "RouterRoleCount", + "code": 16, "mfgCode": null, "side": "server", "included": 1, @@ -2676,8 +1862,8 @@ "reportableChange": 0 }, { - "name": "RxBroadcastCount", - "code": 41, + "name": "LeaderRoleCount", + "code": 17, "mfgCode": null, "side": "server", "included": 1, @@ -2691,8 +1877,8 @@ "reportableChange": 0 }, { - "name": "RxDataCount", - "code": 42, + "name": "AttachAttemptCount", + "code": 18, "mfgCode": null, "side": "server", "included": 1, @@ -2706,8 +1892,8 @@ "reportableChange": 0 }, { - "name": "RxDataPollCount", - "code": 43, + "name": "PartitionIdChangeCount", + "code": 19, "mfgCode": null, "side": "server", "included": 1, @@ -2721,8 +1907,8 @@ "reportableChange": 0 }, { - "name": "RxBeaconCount", - "code": 44, + "name": "BetterPartitionAttachAttemptCount", + "code": 20, "mfgCode": null, "side": "server", "included": 1, @@ -2736,8 +1922,8 @@ "reportableChange": 0 }, { - "name": "RxBeaconRequestCount", - "code": 45, + "name": "ParentChangeCount", + "code": 21, "mfgCode": null, "side": "server", "included": 1, @@ -2751,8 +1937,8 @@ "reportableChange": 0 }, { - "name": "RxOtherCount", - "code": 46, + "name": "TxTotalCount", + "code": 22, "mfgCode": null, "side": "server", "included": 1, @@ -2766,8 +1952,8 @@ "reportableChange": 0 }, { - "name": "RxAddressFilteredCount", - "code": 47, + "name": "TxUnicastCount", + "code": 23, "mfgCode": null, "side": "server", "included": 1, @@ -2781,8 +1967,8 @@ "reportableChange": 0 }, { - "name": "RxDestAddrFilteredCount", - "code": 48, + "name": "TxBroadcastCount", + "code": 24, "mfgCode": null, "side": "server", "included": 1, @@ -2796,8 +1982,8 @@ "reportableChange": 0 }, { - "name": "RxDuplicatedCount", - "code": 49, + "name": "TxAckRequestedCount", + "code": 25, "mfgCode": null, "side": "server", "included": 1, @@ -2811,8 +1997,8 @@ "reportableChange": 0 }, { - "name": "RxErrNoFrameCount", - "code": 50, + "name": "TxAckedCount", + "code": 26, "mfgCode": null, "side": "server", "included": 1, @@ -2826,8 +2012,8 @@ "reportableChange": 0 }, { - "name": "RxErrUnknownNeighborCount", - "code": 51, + "name": "TxNoAckRequestedCount", + "code": 27, "mfgCode": null, "side": "server", "included": 1, @@ -2841,8 +2027,8 @@ "reportableChange": 0 }, { - "name": "RxErrInvalidSrcAddrCount", - "code": 52, + "name": "TxDataCount", + "code": 28, "mfgCode": null, "side": "server", "included": 1, @@ -2856,8 +2042,8 @@ "reportableChange": 0 }, { - "name": "RxErrSecCount", - "code": 53, + "name": "TxDataPollCount", + "code": 29, "mfgCode": null, "side": "server", "included": 1, @@ -2871,8 +2057,8 @@ "reportableChange": 0 }, { - "name": "RxErrFcsCount", - "code": 54, + "name": "TxBeaconCount", + "code": 30, "mfgCode": null, "side": "server", "included": 1, @@ -2886,8 +2072,8 @@ "reportableChange": 0 }, { - "name": "RxErrOtherCount", - "code": 55, + "name": "TxBeaconRequestCount", + "code": 31, "mfgCode": null, "side": "server", "included": 1, @@ -2901,23 +2087,23 @@ "reportableChange": 0 }, { - "name": "SecurityPolicy", - "code": 59, + "name": "TxOtherCount", + "code": 32, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "ChannelMask", - "code": 60, + "name": "TxRetryCount", + "code": 33, "mfgCode": null, "side": "server", "included": 1, @@ -2931,135 +2117,113 @@ "reportableChange": 0 }, { - "name": "OperationalDatasetComponents", - "code": 61, + "name": "TxDirectMaxRetryExpiryCount", + "code": 34, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "ActiveNetworkFaultsList", - "code": 62, + "name": "TxIndirectMaxRetryExpiryCount", + "code": 35, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "cluster revision", - "code": 65533, + "name": "TxErrCcaCount", + "code": 36, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0001", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "WiFi Network Diagnostics", - "code": 54, - "mfgCode": null, - "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [], - "attributes": [ + }, { - "name": "cluster revision", - "code": 65533, + "name": "TxErrAbortCount", + "code": 37, "mfgCode": null, - "side": "client", + "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0001", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "WiFi Network Diagnostics", - "code": 54, - "mfgCode": null, - "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [], - "attributes": [ + }, { - "name": "bssid", - "code": 0, + "name": "TxErrBusyChannelCount", + "code": 38, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "SecurityType", - "code": 1, + "name": "RxTotalCount", + "code": 39, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "WiFiVersion", - "code": 2, + "name": "RxUnicastCount", + "code": 40, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "ChannelNumber", - "code": 3, + "name": "RxBroadcastCount", + "code": 41, "mfgCode": null, "side": "server", "included": 1, @@ -3073,383 +2237,248 @@ "reportableChange": 0 }, { - "name": "Rssi", - "code": 4, + "name": "RxDataCount", + "code": 42, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "cluster revision", - "code": 65533, + "name": "RxDataPollCount", + "code": 43, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0001", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Ethernet Network Diagnostics", - "code": 55, - "mfgCode": null, - "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [ - { - "name": "ResetCounts", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 0, - "outgoing": 1 - } - ], - "attributes": [ + }, { - "name": "cluster revision", - "code": 65533, + "name": "RxBeaconCount", + "code": 44, "mfgCode": null, - "side": "client", + "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0001", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Ethernet Network Diagnostics", - "code": 55, - "mfgCode": null, - "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [], - "attributes": [ + }, { - "name": "PacketRxCount", - "code": 2, + "name": "RxBeaconRequestCount", + "code": 45, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "PacketTxCount", - "code": 3, + "name": "RxOtherCount", + "code": 46, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "TxErrCount", - "code": 4, + "name": "RxAddressFilteredCount", + "code": 47, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "CollisionCount", - "code": 5, + "name": "RxDestAddrFilteredCount", + "code": 48, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "OverrunCount", - "code": 6, + "name": "RxDuplicatedCount", + "code": 49, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "cluster revision", - "code": 65533, + "name": "RxErrNoFrameCount", + "code": 50, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0001", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Operational Credentials", - "code": 62, - "mfgCode": null, - "define": "OPERATIONAL_CREDENTIALS_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [ - { - "name": "SetFabric", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "OpCSRRequest", - "code": 4, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "AddNOC", - "code": 6, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "UpdateFabricLabel", - "code": 9, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "RemoveFabric", - "code": 10, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "RemoveAllFabrics", - "code": 11, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 }, { - "name": "AddTrustedRootCertificate", - "code": 161, + "name": "RxErrUnknownNeighborCount", + "code": 51, "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 }, { - "name": "RemoveTrustedRootCertificate", - "code": 162, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - } - ], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, + "name": "RxErrInvalidSrcAddrCount", + "code": 52, "mfgCode": null, - "side": "client", + "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0001", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Operational Credentials", - "code": 62, - "mfgCode": null, - "define": "OPERATIONAL_CREDENTIALS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "SetFabricResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 }, { - "name": "OpCSRResponse", - "code": 5, + "name": "RxErrSecCount", + "code": 53, "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 }, { - "name": "NOCResponse", - "code": 8, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - } - ], - "attributes": [ - { - "name": "fabrics list", - "code": 1, + "name": "RxErrFcsCount", + "code": 54, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "cluster revision", - "code": 65533, + "name": "RxErrOtherCount", + "code": 55, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0001", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Occupancy Sensing", - "code": 1030, - "mfgCode": null, - "define": "OCCUPANCY_SENSING_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [], - "attributes": [ + }, { - "name": "cluster revision", - "code": 65533, + "name": "SecurityPolicy", + "code": 59, "mfgCode": null, - "side": "client", + "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Occupancy Sensing", - "code": 1030, - "mfgCode": null, - "define": "OCCUPANCY_SENSING_CLUSTER", - "side": "server", - "enabled": 0, - "commands": [], - "attributes": [ + }, { - "name": "occupancy", - "code": 0, + "name": "ChannelMask", + "code": 60, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", - "reportable": 1, + "defaultValue": "0x0000", + "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "occupancy sensor type", - "code": 1, + "name": "OperationalDatasetComponents", + "code": 61, "mfgCode": null, "side": "server", "included": 1, @@ -3463,8 +2492,8 @@ "reportableChange": 0 }, { - "name": "occupancy sensor type bitmap", - "code": 2, + "name": "ActiveNetworkFaultsList", + "code": 62, "mfgCode": null, "side": "server", "included": 1, @@ -3486,27 +2515,19 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 } ] - } - ] - }, - { - "name": "Anonymous Endpoint Type", - "deviceTypeName": "CBA-onofflight", - "deviceTypeCode": 256, - "deviceTypeProfileId": 265, - "clusters": [ + }, { - "name": "Power Configuration", - "code": 1, + "name": "WiFi Network Diagnostics", + "code": 54, "mfgCode": null, - "define": "POWER_CONFIG_CLUSTER", + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", "side": "client", "enabled": 0, "commands": [], @@ -3518,9 +2539,9 @@ "side": "client", "included": 1, "storageOption": "RAM", - "singleton": 1, + "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -3529,106 +2550,84 @@ ] }, { - "name": "Power Configuration", - "code": 1, + "name": "WiFi Network Diagnostics", + "code": 54, "mfgCode": null, - "define": "POWER_CONFIG_CLUSTER", + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", "side": "server", - "enabled": 0, + "enabled": 1, "commands": [], "attributes": [ { - "name": "battery percentage remaining", - "code": 33, + "name": "bssid", + "code": 0, "mfgCode": null, "side": "server", - "included": 0, + "included": 1, "storageOption": "RAM", - "singleton": 1, + "singleton": 0, "bounded": 0, - "defaultValue": "0x00", - "reportable": 1, + "defaultValue": "", + "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "battery alarm state", - "code": 62, + "name": "SecurityType", + "code": 1, "mfgCode": null, "side": "server", - "included": 0, + "included": 1, "storageOption": "RAM", - "singleton": 1, + "singleton": 0, "bounded": 0, - "defaultValue": "0x00000000", - "reportable": 1, + "defaultValue": "", + "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "cluster revision", - "code": 65533, + "name": "WiFiVersion", + "code": 2, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 1, + "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Device Temperature Configuration", - "code": 2, - "mfgCode": null, - "define": "DEVICE_TEMP_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [], - "attributes": [ + }, { - "name": "cluster revision", - "code": 65533, + "name": "ChannelNumber", + "code": 3, "mfgCode": null, - "side": "client", + "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0001", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Device Temperature Configuration", - "code": 2, - "mfgCode": null, - "define": "DEVICE_TEMP_CLUSTER", - "side": "server", - "enabled": 0, - "commands": [], - "attributes": [ + }, { - "name": "current temperature", - "code": 0, + "name": "Rssi", + "code": 4, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x00", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -3652,27 +2651,19 @@ ] }, { - "name": "Identify", - "code": 3, + "name": "Ethernet Network Diagnostics", + "code": 55, "mfgCode": null, - "define": "IDENTIFY_CLUSTER", + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", "side": "client", "enabled": 0, "commands": [ { - "name": "Identify", + "name": "ResetCounts", "code": 0, "mfgCode": null, "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "IdentifyQuery", - "code": 1, - "mfgCode": null, - "source": "client", - "incoming": 1, + "incoming": 0, "outgoing": 1 } ], @@ -3686,7 +2677,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -3695,123 +2686,99 @@ ] }, { - "name": "Identify", - "code": 3, + "name": "Ethernet Network Diagnostics", + "code": 55, "mfgCode": null, - "define": "IDENTIFY_CLUSTER", + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", "side": "server", - "enabled": 0, - "commands": [ - { - "name": "IdentifyQueryResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - } - ], + "enabled": 1, + "commands": [], "attributes": [ { - "name": "identify time", - "code": 0, + "name": "PacketRxCount", + "code": 2, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "0x0000000000000000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "cluster revision", - "code": 65533, + "name": "PacketTxCount", + "code": 3, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "0x0000000000000000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Groups", - "code": 4, - "mfgCode": null, - "define": "GROUPS_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [ - { - "name": "AddGroup", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "ViewGroup", - "code": 1, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 }, { - "name": "GetGroupMembership", - "code": 2, + "name": "TxErrCount", + "code": 4, "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 }, { - "name": "RemoveGroup", - "code": 3, + "name": "CollisionCount", + "code": 5, "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 }, { - "name": "RemoveAllGroups", - "code": 4, + "name": "OverrunCount", + "code": 6, "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 }, - { - "name": "AddGroupIfIdentifying", - "code": 5, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - } - ], - "attributes": [ { "name": "cluster revision", "code": 65533, "mfgCode": null, - "side": "client", + "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "3", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -3820,62 +2787,65 @@ ] }, { - "name": "Groups", - "code": 4, + "name": "AdministratorCommissioning", + "code": 60, "mfgCode": null, - "define": "GROUPS_CLUSTER", - "side": "server", + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", "enabled": 0, "commands": [ { - "name": "AddGroupResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "ViewGroupResponse", - "code": 1, + "name": "OpenCommissioningWindow", + "code": 0, "mfgCode": null, - "source": "server", + "source": "client", "incoming": 1, "outgoing": 1 }, { - "name": "GetGroupMembershipResponse", - "code": 2, + "name": "OpenBasicCommissioningWindow", + "code": 1, "mfgCode": null, - "source": "server", + "source": "client", "incoming": 1, "outgoing": 1 }, { - "name": "RemoveGroupResponse", - "code": 3, + "name": "RevokeCommissioning", + "code": 2, "mfgCode": null, - "source": "server", + "source": "client", "incoming": 1, "outgoing": 1 } ], "attributes": [ { - "name": "name support", - "code": 0, + "name": "cluster revision", + "code": 65533, "mfgCode": null, - "side": "server", + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ { "name": "cluster revision", "code": 65533, @@ -3885,7 +2855,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "3", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -3894,15 +2864,15 @@ ] }, { - "name": "Scenes", - "code": 5, + "name": "Operational Credentials", + "code": 62, "mfgCode": null, - "define": "SCENES_CLUSTER", + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", "side": "client", "enabled": 0, "commands": [ { - "name": "AddScene", + "name": "SetFabric", "code": 0, "mfgCode": null, "source": "client", @@ -3910,52 +2880,60 @@ "outgoing": 1 }, { - "name": "ViewScene", - "code": 1, + "name": "OpCSRRequest", + "code": 4, "mfgCode": null, "source": "client", "incoming": 1, "outgoing": 1 }, { - "name": "RemoveScene", - "code": 2, + "name": "AddNOC", + "code": 6, "mfgCode": null, "source": "client", "incoming": 1, "outgoing": 1 }, { - "name": "RemoveAllScenes", - "code": 3, + "name": "UpdateFabricLabel", + "code": 9, "mfgCode": null, "source": "client", "incoming": 1, "outgoing": 1 }, { - "name": "StoreScene", - "code": 4, + "name": "RemoveFabric", + "code": 10, "mfgCode": null, "source": "client", "incoming": 1, "outgoing": 1 }, { - "name": "RecallScene", - "code": 5, + "name": "RemoveAllFabrics", + "code": 11, "mfgCode": null, "source": "client", "incoming": 1, "outgoing": 1 }, { - "name": "GetSceneMembership", - "code": 6, + "name": "AddTrustedRootCertificate", + "code": 161, "mfgCode": null, "source": "client", "incoming": 1, - "outgoing": 1 + "outgoing": 0 + }, + { + "name": "RemoveTrustedRootCertificate", + "code": 162, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 } ], "attributes": [ @@ -3968,7 +2946,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "3", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -3977,23 +2955,15 @@ ] }, { - "name": "Scenes", - "code": 5, + "name": "Operational Credentials", + "code": 62, "mfgCode": null, - "define": "SCENES_CLUSTER", + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", "side": "server", - "enabled": 0, + "enabled": 1, "commands": [ { - "name": "AddSceneResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "ViewSceneResponse", + "name": "SetFabricResponse", "code": 1, "mfgCode": null, "source": "server", @@ -4001,32 +2971,16 @@ "outgoing": 1 }, { - "name": "RemoveSceneResponse", - "code": 2, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "RemoveAllScenesResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "StoreSceneResponse", - "code": 4, + "name": "OpCSRResponse", + "code": 5, "mfgCode": null, "source": "server", "incoming": 1, "outgoing": 1 }, { - "name": "GetSceneMembershipResponse", - "code": 6, + "name": "NOCResponse", + "code": 8, "mfgCode": null, "source": "server", "incoming": 1, @@ -4035,68 +2989,105 @@ ], "attributes": [ { - "name": "scene count", - "code": 0, + "name": "fabrics list", + "code": 1, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "current scene", - "code": 1, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Occupancy Sensing", + "code": 1030, + "mfgCode": null, + "define": "OCCUPANCY_SENSING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ { - "name": "current group", - "code": 2, + "name": "cluster revision", + "code": 65533, "mfgCode": null, - "side": "server", + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "2", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 + } + ] + }, + { + "name": "Occupancy Sensing", + "code": 1030, + "mfgCode": null, + "define": "OCCUPANCY_SENSING_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "occupancy", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 }, { - "name": "scene valid", - "code": 3, + "name": "occupancy sensor type", + "code": 1, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "name support", - "code": 4, + "name": "occupancy sensor type bitmap", + "code": 2, "mfgCode": null, "side": "server", "included": 1, @@ -4118,47 +3109,30 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "3", + "defaultValue": "2", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 } ] - }, + } + ] + }, + { + "name": "Anonymous Endpoint Type", + "deviceTypeName": null, + "deviceTypeCode": null, + "deviceTypeProfileId": null, + "clusters": [ { - "name": "On/off", - "code": 6, + "name": "Power Configuration", + "code": 1, "mfgCode": null, - "define": "ON_OFF_CLUSTER", + "define": "POWER_CONFIG_CLUSTER", "side": "client", "enabled": 0, - "commands": [ - { - "name": "Off", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "On", - "code": 1, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "Toggle", - "code": 2, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - } - ], + "commands": [], "attributes": [ { "name": "cluster revision", @@ -4167,7 +3141,7 @@ "side": "client", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, "defaultValue": "2", "reportable": 0, @@ -4178,24 +3152,39 @@ ] }, { - "name": "On/off", - "code": 6, + "name": "Power Configuration", + "code": 1, "mfgCode": null, - "define": "ON_OFF_CLUSTER", + "define": "POWER_CONFIG_CLUSTER", "side": "server", - "enabled": 1, + "enabled": 0, "commands": [], "attributes": [ { - "name": "on/off", - "code": 0, + "name": "battery percentage remaining", + "code": 33, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "battery alarm state", + "code": 62, "mfgCode": null, "side": "server", - "included": 1, + "included": 0, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "0x00000000", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -4208,7 +3197,7 @@ "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, "defaultValue": "2", "reportable": 0, @@ -4219,10 +3208,10 @@ ] }, { - "name": "On/off Switch Configuration", - "code": 7, + "name": "Device Temperature Configuration", + "code": 2, "mfgCode": null, - "define": "ON_OFF_SWITCH_CONFIG_CLUSTER", + "define": "DEVICE_TEMP_CLUSTER", "side": "client", "enabled": 0, "commands": [], @@ -4245,16 +3234,16 @@ ] }, { - "name": "On/off Switch Configuration", - "code": 7, + "name": "Device Temperature Configuration", + "code": 2, "mfgCode": null, - "define": "ON_OFF_SWITCH_CONFIG_CLUSTER", + "define": "DEVICE_TEMP_CLUSTER", "side": "server", "enabled": 0, "commands": [], "attributes": [ { - "name": "switch type", + "name": "current temperature", "code": 0, "mfgCode": null, "side": "server", @@ -4268,21 +3257,6 @@ "maxInterval": 65344, "reportableChange": 0 }, - { - "name": "switch actions", - "code": 16, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x00", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, { "name": "cluster revision", "code": 65533, @@ -4301,28 +3275,28 @@ ] }, { - "name": "Alarms", - "code": 9, + "name": "Identify", + "code": 3, "mfgCode": null, - "define": "ALARM_CLUSTER", + "define": "IDENTIFY_CLUSTER", "side": "client", "enabled": 0, "commands": [ { - "name": "ResetAlarm", + "name": "Identify", "code": 0, "mfgCode": null, "source": "client", "incoming": 1, - "outgoing": 0 + "outgoing": 1 }, { - "name": "ResetAllAlarms", + "name": "IdentifyQuery", "code": 1, "mfgCode": null, "source": "client", "incoming": 1, - "outgoing": 0 + "outgoing": 1 } ], "attributes": [ @@ -4335,7 +3309,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0001", + "defaultValue": "2", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -4344,23 +3318,38 @@ ] }, { - "name": "Alarms", - "code": 9, + "name": "Identify", + "code": 3, "mfgCode": null, - "define": "ALARM_CLUSTER", + "define": "IDENTIFY_CLUSTER", "side": "server", "enabled": 0, "commands": [ { - "name": "Alarm", + "name": "IdentifyQueryResponse", "code": 0, "mfgCode": null, "source": "server", - "incoming": 0, + "incoming": 1, "outgoing": 1 } ], "attributes": [ + { + "name": "identify time", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, { "name": "cluster revision", "code": 65533, @@ -4370,7 +3359,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0001", + "defaultValue": "2", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -4379,28 +3368,60 @@ ] }, { - "name": "Commissioning", - "code": 21, + "name": "Groups", + "code": 4, "mfgCode": null, - "define": "COMMISSIONING_CLUSTER", + "define": "GROUPS_CLUSTER", "side": "client", "enabled": 0, "commands": [ { - "name": "RestartDevice", + "name": "AddGroup", "code": 0, "mfgCode": null, "source": "client", "incoming": 1, - "outgoing": 0 + "outgoing": 1 + }, + { + "name": "ViewGroup", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetGroupMembership", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "ResetStartupParameters", + "name": "RemoveGroup", "code": 3, "mfgCode": null, "source": "client", "incoming": 1, - "outgoing": 0 + "outgoing": 1 + }, + { + "name": "RemoveAllGroups", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "AddGroupIfIdentifying", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 } ], "attributes": [ @@ -4413,7 +3434,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -4422,49 +3443,49 @@ ] }, { - "name": "Commissioning", - "code": 21, + "name": "Groups", + "code": 4, "mfgCode": null, - "define": "COMMISSIONING_CLUSTER", + "define": "GROUPS_CLUSTER", "side": "server", "enabled": 0, "commands": [ { - "name": "RestartDeviceResponse", + "name": "AddGroupResponse", "code": 0, "mfgCode": null, "source": "server", - "incoming": 0, + "incoming": 1, "outgoing": 1 }, { - "name": "SaveStartupParametersResponse", + "name": "ViewGroupResponse", "code": 1, "mfgCode": null, "source": "server", - "incoming": 0, + "incoming": 1, "outgoing": 1 }, { - "name": "RestoreStartupParametersResponse", + "name": "GetGroupMembershipResponse", "code": 2, "mfgCode": null, "source": "server", - "incoming": 0, + "incoming": 1, "outgoing": 1 }, { - "name": "ResetStartupParametersResponse", + "name": "RemoveGroupResponse", "code": 3, "mfgCode": null, "source": "server", - "incoming": 0, + "incoming": 1, "outgoing": 1 } ], "attributes": [ { - "name": "short address", + "name": "name support", "code": 0, "mfgCode": null, "side": "server", @@ -4472,285 +3493,392 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0xFFFF", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "extended pan id", - "code": 1, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0xFFFFFFFFFFFFFFFF", + "defaultValue": "3", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddScene", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewScene", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "pan id", + "name": "RemoveScene", "code": 2, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0xFFFF", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "channel mask", + "name": "RemoveAllScenes", "code": 3, "mfgCode": null, - "side": "server", + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "StoreScene", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RecallScene", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "GetSceneMembership", + "code": 6, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x07FFF800", + "defaultValue": "3", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 + } + ] + }, + { + "name": "Scenes", + "code": 5, + "mfgCode": null, + "define": "SCENES_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "AddSceneResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "ViewSceneResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RemoveSceneResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 }, { - "name": "protocol version", - "code": 4, + "name": "RemoveAllScenesResponse", + "code": 3, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x02", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 1, + "outgoing": 1 }, { - "name": "stack profile", - "code": 5, + "name": "StoreSceneResponse", + "code": 4, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x02", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 1, + "outgoing": 1 }, { - "name": "startup control", + "name": "GetSceneMembershipResponse", "code": 6, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x03", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ { - "name": "trust center address", - "code": 16, + "name": "scene count", + "code": 0, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": "0x00", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "network key", - "code": 18, + "name": "current scene", + "code": 1, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00000000000000000000000000000000", + "defaultValue": "0x00", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "use insecure join", - "code": 19, + "name": "current group", + "code": 2, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x01", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "preconfigured link key", - "code": 20, + "name": "scene valid", + "code": 3, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00000000000000000000000000000000", + "defaultValue": "0x00", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "network key sequence number", - "code": 21, + "name": "name support", + "code": 4, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "network key type", - "code": 22, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x05", + "defaultValue": "3", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "On/off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ { - "name": "network manager address", - "code": 23, + "name": "Off", + "code": 0, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "scan attempts", - "code": 32, + "name": "On", + "code": 1, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x05", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "time between scans", - "code": 33, + "name": "Toggle", + "code": 2, "mfgCode": null, - "side": "server", + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0064", + "defaultValue": "2", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "On/off", + "code": 6, + "mfgCode": null, + "define": "ON_OFF_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ { - "name": "rejoin interval", - "code": 34, + "name": "OnOff", + "code": 0, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x003C", - "reportable": 0, + "defaultValue": "0x00", + "reportable": 1, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "max rejoin interval", - "code": 35, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0E10", + "defaultValue": "2", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "On/off Switch Configuration", + "code": 7, + "mfgCode": null, + "define": "ON_OFF_SWITCH_CONFIG_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ { - "name": "indirect poll rate", - "code": 48, + "name": "cluster revision", + "code": 65533, "mfgCode": null, - "side": "server", + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "On/off Switch Configuration", + "code": 7, + "mfgCode": null, + "define": "ON_OFF_SWITCH_CONFIG_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [], + "attributes": [ { - "name": "parent retry threshold", - "code": 49, + "name": "switch type", + "code": 0, "mfgCode": null, "side": "server", "included": 1, @@ -4764,8 +3892,8 @@ "reportableChange": 0 }, { - "name": "concentrator flag", - "code": 64, + "name": "switch actions", + "code": 16, "mfgCode": null, "side": "server", "included": 1, @@ -4779,35 +3907,83 @@ "reportableChange": 0 }, { - "name": "concentrator radius", - "code": 65, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0F", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 + } + ] + }, + { + "name": "Alarms", + "code": 9, + "mfgCode": null, + "define": "ALARM_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetAlarm", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 }, { - "name": "concentrator discovery time", - "code": 66, + "name": "ResetAllAlarms", + "code": 1, "mfgCode": null, - "side": "server", + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Alarms", + "code": 9, + "mfgCode": null, + "define": "ALARM_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "Alarm", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ { "name": "cluster revision", "code": 65533, @@ -4817,7 +3993,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -5188,4 +4364,4 @@ } ], "log": [] -} +} \ No newline at end of file diff --git a/examples/lock-app/mbed/CMakeLists.txt b/examples/lock-app/mbed/CMakeLists.txt index 1cecc1c69b585e..e66cddabc117b1 100644 --- a/examples/lock-app/mbed/CMakeLists.txt +++ b/examples/lock-app/mbed/CMakeLists.txt @@ -73,6 +73,7 @@ target_sources(${APP_TARGET} PRIVATE ${CHIP_ROOT}/src/app/server/RendezvousServer.cpp ${CHIP_ROOT}/src/app/server/Server.cpp ${CHIP_ROOT}/src/app/server/StorablePeerConnection.cpp + ${CHIP_ROOT}/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp ${CHIP_ROOT}/src/app/clusters/basic/basic.cpp ${CHIP_ROOT}/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp ${CHIP_ROOT}/src/app/clusters/bindings/bindings.cpp diff --git a/examples/lock-app/nrfconnect/CMakeLists.txt b/examples/lock-app/nrfconnect/CMakeLists.txt index 72307e3fad6d09..a1d6455a650b76 100644 --- a/examples/lock-app/nrfconnect/CMakeLists.txt +++ b/examples/lock-app/nrfconnect/CMakeLists.txt @@ -86,6 +86,7 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/server/RendezvousServer.cpp ${CHIP_ROOT}/src/app/server/Server.cpp ${CHIP_ROOT}/src/app/server/StorablePeerConnection.cpp + ${CHIP_ROOT}/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp ${CHIP_ROOT}/src/app/clusters/basic/basic.cpp ${CHIP_ROOT}/src/app/clusters/bindings/bindings.cpp ${CHIP_ROOT}/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp diff --git a/examples/pump-app/nrfconnect/CMakeLists.txt b/examples/pump-app/nrfconnect/CMakeLists.txt index b7574f0dfd69f4..e5e278befb0df9 100644 --- a/examples/pump-app/nrfconnect/CMakeLists.txt +++ b/examples/pump-app/nrfconnect/CMakeLists.txt @@ -65,6 +65,7 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/util/process-cluster-message.cpp ${CHIP_ROOT}/src/app/util/process-global-message.cpp ${CHIP_ROOT}/src/app/util/util.cpp + ${CHIP_ROOT}/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp ${CHIP_ROOT}/src/app/clusters/bindings/bindings.cpp ${CHIP_ROOT}/src/app/clusters/on-off-server/on-off.cpp ${CHIP_ROOT}/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp) diff --git a/examples/pump-app/pump-common/gen/IMClusterCommandHandler.cpp b/examples/pump-app/pump-common/gen/IMClusterCommandHandler.cpp index c5a014fe634d3c..cdbacc589f45ff 100644 --- a/examples/pump-app/pump-common/gen/IMClusterCommandHandler.cpp +++ b/examples/pump-app/pump-common/gen/IMClusterCommandHandler.cpp @@ -51,6 +51,203 @@ void ReportCommandUnsupported(Command * aCommandObj, EndpointId aEndpointId, Clu namespace clusters { +namespace AdministratorCommissioning { + +void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, + TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case Clusters::AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow: { + expectArgumentCount = 1; + uint16_t CommissioningTimeout; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(aEndpointId, apCommandObj, + CommissioningTimeout); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow: { + expectArgumentCount = 6; + uint16_t CommissioningTimeout; + chip::ByteSpan PAKEVerifier; + uint16_t Discriminator; + uint32_t Iterations; + chip::ByteSpan Salt; + uint16_t PasscodeID; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + PAKEVerifier = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: + TLVUnpackError = aDataTlv.Get(Discriminator); + break; + case 3: + TLVUnpackError = aDataTlv.Get(Iterations); + break; + case 4: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + Salt = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 5: + TLVUnpackError = aDataTlv.Get(PasscodeID); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( + aEndpointId, apCommandObj, CommissioningTimeout, PAKEVerifier, Discriminator, Iterations, Salt, PasscodeID); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::RevokeCommissioning: { + + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(aEndpointId, apCommandObj); + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::AdministratorCommissioning::Id, aCommandId); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + Clusters::AdministratorCommissioning::Id, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT + ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError), + ChipError::FormatError(TLVUnpackError), currentDecodeTagId); + // A command with no arguments would never write currentDecodeTagId. If + // progress logging is also disabled, it would look unused. Silence that + // warning. + UNUSED_VAR(currentDecodeTagId); + } +} + +} // namespace AdministratorCommissioning + namespace Basic { void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, @@ -2092,6 +2289,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case Clusters::AdministratorCommissioning::Id: + clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case Clusters::Basic::Id: clusters::Basic::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/pump-app/pump-common/gen/callback-stub.cpp b/examples/pump-app/pump-common/gen/callback-stub.cpp index b5285e115753f9..c589e2dbc49fc3 100644 --- a/examples/pump-app/pump-common/gen/callback-stub.cpp +++ b/examples/pump-app/pump-common/gen/callback-stub.cpp @@ -28,6 +28,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) { switch (clusterId) { + case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID: + emberAfAdministratorCommissioningClusterInitCallback(endpoint); + break; case ZCL_BASIC_CLUSTER_ID: emberAfBasicClusterInitCallback(endpoint); break; @@ -82,6 +85,11 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) } } +void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/pump-app/pump-common/gen/endpoint_config.h b/examples/pump-app/pump-common/gen/endpoint_config.h index 5936766d8b66a8..4c091c351700d3 100644 --- a/examples/pump-app/pump-common/gen/endpoint_config.h +++ b/examples/pump-app/pump-common/gen/endpoint_config.h @@ -583,7 +583,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 123 +#define GENERATED_ATTRIBUTE_COUNT 124 #define GENERATED_ATTRIBUTES \ { \ \ @@ -709,6 +709,9 @@ { 0x0006, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1264) }, /* OverrunCount */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0001, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(1272) }, /* fabrics list */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ @@ -771,7 +774,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 19 +#define GENERATED_CLUSTER_COUNT 20 #define GENERATED_CLUSTERS \ { \ { \ @@ -819,33 +822,36 @@ 0x0037, ZAP_ATTRIBUTE_INDEX(92), 6, 42, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { \ - 0x003E, ZAP_ATTRIBUTE_INDEX(98), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x003C, ZAP_ATTRIBUTE_INDEX(98), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { \ + 0x003E, ZAP_ATTRIBUTE_INDEX(99), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { \ 0x0200, \ - ZAP_ATTRIBUTE_INDEX(100), \ + ZAP_ATTRIBUTE_INDEX(101), \ 8, \ 13, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayPumpConfigurationAndControlServer \ }, /* Endpoint: 1, Cluster: Pump Configuration and Control (server) */ \ { \ - 0x0402, ZAP_ATTRIBUTE_INDEX(108), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0402, ZAP_ATTRIBUTE_INDEX(109), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Temperature Measurement (client) */ \ { \ - 0x0402, ZAP_ATTRIBUTE_INDEX(109), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0402, ZAP_ATTRIBUTE_INDEX(110), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Temperature Measurement (server) */ \ { \ - 0x0403, ZAP_ATTRIBUTE_INDEX(113), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0403, ZAP_ATTRIBUTE_INDEX(114), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Pressure Measurement (client) */ \ { \ - 0x0403, ZAP_ATTRIBUTE_INDEX(114), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0403, ZAP_ATTRIBUTE_INDEX(115), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Pressure Measurement (server) */ \ { \ - 0x0404, ZAP_ATTRIBUTE_INDEX(118), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0404, ZAP_ATTRIBUTE_INDEX(119), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Flow Measurement (client) */ \ { \ - 0x0404, ZAP_ATTRIBUTE_INDEX(119), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0404, ZAP_ATTRIBUTE_INDEX(120), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Flow Measurement (server) */ \ } @@ -854,7 +860,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 12, 1592 }, { ZAP_CLUSTER_INDEX(12), 7, 43 }, \ + { ZAP_CLUSTER_INDEX(0), 13, 1594 }, { ZAP_CLUSTER_INDEX(13), 7, 43 }, \ } // Largest attribute size is needed for various buffers @@ -864,7 +870,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (240) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (1635) +#define ATTRIBUTE_MAX_SIZE (1637) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (2) @@ -908,7 +914,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (53) +#define EMBER_AF_GENERATED_COMMAND_COUNT (56) #define GENERATED_COMMANDS \ { \ \ @@ -972,6 +978,11 @@ /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { 0x0037, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetCounts */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0x003C, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenCommissioningWindow */ \ + { 0x003C, 0x01, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenBasicCommissioningWindow */ \ + { 0x003C, 0x02, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RevokeCommissioning */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x003E, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* SetFabric */ \ { 0x003E, 0x01, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* SetFabricResponse */ \ diff --git a/examples/pump-app/pump-common/gen/gen_config.h b/examples/pump-app/pump-common/gen/gen_config.h index 9e8741ee02ce0b..a2e7c1eb73cbdf 100644 --- a/examples/pump-app/pump-common/gen/gen_config.h +++ b/examples/pump-app/pump-common/gen/gen_config.h @@ -29,6 +29,7 @@ #define EMBER_APS_UNICAST_MESSAGE_COUNT 10 /**** Cluster endpoint counts ****/ +#define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -51,6 +52,11 @@ /**** Cluster Plugins ****/ +// Use this macro to check if the server side of the AdministratorCommissioning cluster is included +#define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING + // Use this macro to check if the server side of the Basic cluster is included #define ZCL_USING_BASIC_CLUSTER_SERVER #define EMBER_AF_PLUGIN_BASIC_SERVER diff --git a/examples/pump-app/pump-common/pump-app.zap b/examples/pump-app/pump-common/pump-app.zap index bd9c7bd0468176..ae6b07151b57dd 100644 --- a/examples/pump-app/pump-common/pump-app.zap +++ b/examples/pump-app/pump-common/pump-app.zap @@ -572,7 +572,7 @@ "commands": [], "attributes": [ { - "name": "on/off", + "name": "OnOff", "code": 0, "mfgCode": null, "side": "server", @@ -1323,16 +1323,9 @@ "source": "client", "incoming": 1, "outgoing": 0 - }, - { - "name": "RetrieveLogsResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 } - ] + ], + "attributes": [] }, { "name": "General Diagnostics", @@ -2716,6 +2709,83 @@ } ] }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "Operational Credentials", "code": 62, @@ -3955,7 +4025,7 @@ "commands": [], "attributes": [ { - "name": "on/off", + "name": "OnOff", "code": 0, "mfgCode": null, "side": "server", @@ -4931,4 +5001,4 @@ } ], "log": [] -} +} \ No newline at end of file diff --git a/examples/pump-controller-app/nrfconnect/CMakeLists.txt b/examples/pump-controller-app/nrfconnect/CMakeLists.txt index 906b6cde4610f1..a068c95041ae43 100644 --- a/examples/pump-controller-app/nrfconnect/CMakeLists.txt +++ b/examples/pump-controller-app/nrfconnect/CMakeLists.txt @@ -65,6 +65,7 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/util/process-cluster-message.cpp ${CHIP_ROOT}/src/app/util/process-global-message.cpp ${CHIP_ROOT}/src/app/util/util.cpp + ${CHIP_ROOT}/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp ${CHIP_ROOT}/src/app/clusters/bindings/bindings.cpp ${CHIP_ROOT}/src/app/clusters/on-off-server/on-off.cpp ${CHIP_ROOT}/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp) diff --git a/examples/pump-controller-app/pump-controller-common/gen/IMClusterCommandHandler.cpp b/examples/pump-controller-app/pump-controller-common/gen/IMClusterCommandHandler.cpp index 30bf8325ea9e8b..e4947d4d18fc4d 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/IMClusterCommandHandler.cpp +++ b/examples/pump-controller-app/pump-controller-common/gen/IMClusterCommandHandler.cpp @@ -51,6 +51,203 @@ void ReportCommandUnsupported(Command * aCommandObj, EndpointId aEndpointId, Clu namespace clusters { +namespace AdministratorCommissioning { + +void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, + TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case Clusters::AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow: { + expectArgumentCount = 1; + uint16_t CommissioningTimeout; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(aEndpointId, apCommandObj, + CommissioningTimeout); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow: { + expectArgumentCount = 6; + uint16_t CommissioningTimeout; + chip::ByteSpan PAKEVerifier; + uint16_t Discriminator; + uint32_t Iterations; + chip::ByteSpan Salt; + uint16_t PasscodeID; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + PAKEVerifier = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: + TLVUnpackError = aDataTlv.Get(Discriminator); + break; + case 3: + TLVUnpackError = aDataTlv.Get(Iterations); + break; + case 4: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + Salt = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 5: + TLVUnpackError = aDataTlv.Get(PasscodeID); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( + aEndpointId, apCommandObj, CommissioningTimeout, PAKEVerifier, Discriminator, Iterations, Salt, PasscodeID); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::RevokeCommissioning: { + + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(aEndpointId, apCommandObj); + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::AdministratorCommissioning::Id, aCommandId); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + Clusters::AdministratorCommissioning::Id, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT + ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError), + ChipError::FormatError(TLVUnpackError), currentDecodeTagId); + // A command with no arguments would never write currentDecodeTagId. If + // progress logging is also disabled, it would look unused. Silence that + // warning. + UNUSED_VAR(currentDecodeTagId); + } +} + +} // namespace AdministratorCommissioning + namespace Basic { void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, @@ -1564,6 +1761,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case Clusters::AdministratorCommissioning::Id: + clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case Clusters::Basic::Id: clusters::Basic::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/pump-controller-app/pump-controller-common/gen/callback-stub.cpp b/examples/pump-controller-app/pump-controller-common/gen/callback-stub.cpp index b5285e115753f9..c589e2dbc49fc3 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/callback-stub.cpp +++ b/examples/pump-controller-app/pump-controller-common/gen/callback-stub.cpp @@ -28,6 +28,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) { switch (clusterId) { + case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID: + emberAfAdministratorCommissioningClusterInitCallback(endpoint); + break; case ZCL_BASIC_CLUSTER_ID: emberAfBasicClusterInitCallback(endpoint); break; @@ -82,6 +85,11 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) } } +void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/pump-controller-app/pump-controller-common/gen/endpoint_config.h b/examples/pump-controller-app/pump-controller-common/gen/endpoint_config.h index edc9c29851dc95..fce3d81467e6cc 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/endpoint_config.h +++ b/examples/pump-controller-app/pump-controller-common/gen/endpoint_config.h @@ -583,7 +583,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 102 +#define GENERATED_ATTRIBUTE_COUNT 103 #define GENERATED_ATTRIBUTES \ { \ \ @@ -707,6 +707,9 @@ { 0x0006, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1264) }, /* OverrunCount */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0001, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(1272) }, /* fabrics list */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ @@ -734,7 +737,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 16 +#define GENERATED_CLUSTER_COUNT 17 #define GENERATED_CLUSTERS \ { \ { 0x0006, ZAP_ATTRIBUTE_INDEX(0), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL }, /* Endpoint: 0, Cluster: On/off (client) */ \ @@ -772,19 +775,22 @@ 0x0037, ZAP_ATTRIBUTE_INDEX(90), 6, 42, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { \ - 0x003E, ZAP_ATTRIBUTE_INDEX(96), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x003C, ZAP_ATTRIBUTE_INDEX(96), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { \ + 0x003E, ZAP_ATTRIBUTE_INDEX(97), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { \ - 0x0200, ZAP_ATTRIBUTE_INDEX(98), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0200, ZAP_ATTRIBUTE_INDEX(99), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Pump Configuration and Control (client) */ \ { \ - 0x0402, ZAP_ATTRIBUTE_INDEX(99), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0402, ZAP_ATTRIBUTE_INDEX(100), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Temperature Measurement (client) */ \ { \ - 0x0403, ZAP_ATTRIBUTE_INDEX(100), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0403, ZAP_ATTRIBUTE_INDEX(101), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Pressure Measurement (client) */ \ { \ - 0x0404, ZAP_ATTRIBUTE_INDEX(101), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0404, ZAP_ATTRIBUTE_INDEX(102), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Flow Measurement (client) */ \ } @@ -793,7 +799,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 12, 1590 }, { ZAP_CLUSTER_INDEX(12), 4, 8 }, \ + { ZAP_CLUSTER_INDEX(0), 13, 1592 }, { ZAP_CLUSTER_INDEX(13), 4, 8 }, \ } // Largest attribute size is needed for various buffers @@ -803,7 +809,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (240) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (1598) +#define ATTRIBUTE_MAX_SIZE (1600) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (2) @@ -847,7 +853,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (53) +#define EMBER_AF_GENERATED_COMMAND_COUNT (56) #define GENERATED_COMMANDS \ { \ \ @@ -911,6 +917,11 @@ /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { 0x0037, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetCounts */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0x003C, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenCommissioningWindow */ \ + { 0x003C, 0x01, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenBasicCommissioningWindow */ \ + { 0x003C, 0x02, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RevokeCommissioning */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x003E, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* SetFabric */ \ { 0x003E, 0x01, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* SetFabricResponse */ \ diff --git a/examples/pump-controller-app/pump-controller-common/gen/gen_config.h b/examples/pump-controller-app/pump-controller-common/gen/gen_config.h index 99c741e458b8c9..4b5c26ab4323ef 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/gen_config.h +++ b/examples/pump-controller-app/pump-controller-common/gen/gen_config.h @@ -29,6 +29,7 @@ #define EMBER_APS_UNICAST_MESSAGE_COUNT 10 /**** Cluster endpoint counts ****/ +#define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -48,6 +49,11 @@ /**** Cluster Plugins ****/ +// Use this macro to check if the server side of the AdministratorCommissioning cluster is included +#define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING + // Use this macro to check if the server side of the Basic cluster is included #define ZCL_USING_BASIC_CLUSTER_SERVER #define EMBER_AF_PLUGIN_BASIC_SERVER diff --git a/examples/pump-controller-app/pump-controller-common/pump-controller-app.zap b/examples/pump-controller-app/pump-controller-common/pump-controller-app.zap index e34a5500fb9501..fcbb58d63e4aae 100644 --- a/examples/pump-controller-app/pump-controller-common/pump-controller-app.zap +++ b/examples/pump-controller-app/pump-controller-common/pump-controller-app.zap @@ -572,7 +572,7 @@ "commands": [], "attributes": [ { - "name": "on/off", + "name": "OnOff", "code": 0, "mfgCode": null, "side": "server", @@ -1323,16 +1323,9 @@ "source": "client", "incoming": 1, "outgoing": 0 - }, - { - "name": "RetrieveLogsResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 } - ] + ], + "attributes": [] }, { "name": "General Diagnostics", @@ -2716,6 +2709,83 @@ } ] }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "Operational Credentials", "code": 62, @@ -3955,7 +4025,7 @@ "commands": [], "attributes": [ { - "name": "on/off", + "name": "OnOff", "code": 0, "mfgCode": null, "side": "server", @@ -4931,4 +5001,4 @@ } ], "log": [] -} +} \ No newline at end of file diff --git a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt index 4abdcab9cf315d..6438df9827de12 100644 --- a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt +++ b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt @@ -28,6 +28,7 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" diff --git a/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp b/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp index b9c9810b545d55..2cab5ac53ee071 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp +++ b/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp @@ -51,6 +51,203 @@ void ReportCommandUnsupported(Command * aCommandObj, EndpointId aEndpointId, Clu namespace clusters { +namespace AdministratorCommissioning { + +void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, + TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case Clusters::AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow: { + expectArgumentCount = 1; + uint16_t CommissioningTimeout; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(aEndpointId, apCommandObj, + CommissioningTimeout); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow: { + expectArgumentCount = 6; + uint16_t CommissioningTimeout; + chip::ByteSpan PAKEVerifier; + uint16_t Discriminator; + uint32_t Iterations; + chip::ByteSpan Salt; + uint16_t PasscodeID; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + PAKEVerifier = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: + TLVUnpackError = aDataTlv.Get(Discriminator); + break; + case 3: + TLVUnpackError = aDataTlv.Get(Iterations); + break; + case 4: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + Salt = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 5: + TLVUnpackError = aDataTlv.Get(PasscodeID); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( + aEndpointId, apCommandObj, CommissioningTimeout, PAKEVerifier, Discriminator, Iterations, Salt, PasscodeID); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::RevokeCommissioning: { + + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(aEndpointId, apCommandObj); + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::AdministratorCommissioning::Id, aCommandId); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + Clusters::AdministratorCommissioning::Id, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT + ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError), + ChipError::FormatError(TLVUnpackError), currentDecodeTagId); + // A command with no arguments would never write currentDecodeTagId. If + // progress logging is also disabled, it would look unused. Silence that + // warning. + UNUSED_VAR(currentDecodeTagId); + } +} + +} // namespace AdministratorCommissioning + namespace DiagnosticLogs { void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, @@ -1414,6 +1611,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case Clusters::AdministratorCommissioning::Id: + clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case Clusters::DiagnosticLogs::Id: clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/temperature-measurement-app/esp32/main/gen/callback-stub.cpp b/examples/temperature-measurement-app/esp32/main/gen/callback-stub.cpp index d4f6ee55e79a09..73b9edb6471bd1 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/callback-stub.cpp +++ b/examples/temperature-measurement-app/esp32/main/gen/callback-stub.cpp @@ -28,6 +28,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) { switch (clusterId) { + case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID: + emberAfAdministratorCommissioningClusterInitCallback(endpoint); + break; case ZCL_BASIC_CLUSTER_ID: emberAfBasicClusterInitCallback(endpoint); break; @@ -64,6 +67,11 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) } } +void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/temperature-measurement-app/esp32/main/gen/endpoint_config.h b/examples/temperature-measurement-app/esp32/main/gen/endpoint_config.h index fb6f75ea9e0f8a..481b81021de0dd 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/endpoint_config.h +++ b/examples/temperature-measurement-app/esp32/main/gen/endpoint_config.h @@ -263,7 +263,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 39 +#define GENERATED_ATTRIBUTE_COUNT 40 #define GENERATED_ATTRIBUTES \ { \ \ @@ -318,6 +318,9 @@ { 0x0006, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(544) }, /* OverrunCount */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0001, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(552) }, /* fabrics list */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ @@ -339,7 +342,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 10 +#define GENERATED_CLUSTER_COUNT 11 #define GENERATED_CLUSTERS \ { \ { 0x0028, \ @@ -370,10 +373,13 @@ 0x0037, ZAP_ATTRIBUTE_INDEX(27), 6, 42, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { \ - 0x003E, ZAP_ATTRIBUTE_INDEX(33), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x003C, ZAP_ATTRIBUTE_INDEX(33), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { \ + 0x003E, ZAP_ATTRIBUTE_INDEX(34), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { \ - 0x0402, ZAP_ATTRIBUTE_INDEX(35), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0402, ZAP_ATTRIBUTE_INDEX(36), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Temperature Measurement (server) */ \ } @@ -382,7 +388,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 9, 839 }, { ZAP_CLUSTER_INDEX(9), 1, 8 }, \ + { ZAP_CLUSTER_INDEX(0), 10, 841 }, { ZAP_CLUSTER_INDEX(10), 1, 8 }, \ } // Largest attribute size is needed for various buffers @@ -392,7 +398,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (240) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (847) +#define ATTRIBUTE_MAX_SIZE (849) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (2) @@ -436,7 +442,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (36) +#define EMBER_AF_GENERATED_COMMAND_COUNT (39) #define GENERATED_COMMANDS \ { \ \ @@ -477,6 +483,11 @@ /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { 0x0037, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetCounts */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0x003C, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenCommissioningWindow */ \ + { 0x003C, 0x01, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenBasicCommissioningWindow */ \ + { 0x003C, 0x02, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RevokeCommissioning */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x003E, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* SetFabric */ \ { 0x003E, 0x01, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* SetFabricResponse */ \ diff --git a/examples/temperature-measurement-app/esp32/main/gen/gen_config.h b/examples/temperature-measurement-app/esp32/main/gen/gen_config.h index d6debf84014402..11dbedc81dbd68 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/gen_config.h +++ b/examples/temperature-measurement-app/esp32/main/gen/gen_config.h @@ -29,6 +29,7 @@ #define EMBER_APS_UNICAST_MESSAGE_COUNT 10 /**** Cluster endpoint counts ****/ +#define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -42,6 +43,11 @@ /**** Cluster Plugins ****/ +// Use this macro to check if the server side of the AdministratorCommissioning cluster is included +#define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING + // Use this macro to check if the server side of the Basic cluster is included #define ZCL_USING_BASIC_CLUSTER_SERVER #define EMBER_AF_PLUGIN_BASIC_SERVER diff --git a/examples/temperature-measurement-app/esp32/main/temperature-measurement.zap b/examples/temperature-measurement-app/esp32/main/temperature-measurement.zap index ffd26813cc2c2f..1129b19afe977c 100644 --- a/examples/temperature-measurement-app/esp32/main/temperature-measurement.zap +++ b/examples/temperature-measurement-app/esp32/main/temperature-measurement.zap @@ -1,5 +1,5 @@ { - "featureLevel": 35, + "featureLevel": 45, "creator": "zap", "keyValuePairs": [ { @@ -32,9 +32,9 @@ "endpointTypes": [ { "name": "Anonymous Endpoint Type", - "deviceTypeName": "CBA-tempsensor", - "deviceTypeCode": 770, - "deviceTypeProfileId": 261, + "deviceTypeName": null, + "deviceTypeCode": null, + "deviceTypeProfileId": null, "clusters": [ { "name": "Power Configuration", @@ -439,30 +439,13 @@ ] }, { - "name": "Commissioning", - "code": 21, + "name": "Basic", + "code": 40, "mfgCode": null, - "define": "COMMISSIONING_CLUSTER", + "define": "BASIC_CLUSTER", "side": "client", "enabled": 0, - "commands": [ - { - "name": "RestartDevice", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "ResetStartupParameters", - "code": 3, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - } - ], + "commands": [], "attributes": [ { "name": "cluster revision", @@ -471,9 +454,9 @@ "side": "client", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -482,335 +465,324 @@ ] }, { - "name": "Commissioning", - "code": 21, + "name": "Basic", + "code": 40, "mfgCode": null, - "define": "COMMISSIONING_CLUSTER", + "define": "BASIC_CLUSTER", "side": "server", - "enabled": 0, + "enabled": 1, "commands": [ { - "name": "RestartDeviceResponse", + "name": "StartUp", "code": 0, "mfgCode": null, "source": "server", - "incoming": 0, + "incoming": 1, "outgoing": 1 }, { - "name": "SaveStartupParametersResponse", + "name": "ShutDown", "code": 1, "mfgCode": null, "source": "server", - "incoming": 0, + "incoming": 1, "outgoing": 1 }, { - "name": "RestoreStartupParametersResponse", + "name": "Leave", "code": 2, "mfgCode": null, "source": "server", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "ResetStartupParametersResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "incoming": 0, + "incoming": 1, "outgoing": 1 } ], "attributes": [ { - "name": "short address", + "name": "InteractionModelVersion", "code": 0, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0xFFFF", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "extended pan id", + "name": "VendorName", "code": 1, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0xFFFFFFFFFFFFFFFF", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "pan id", + "name": "VendorID", "code": 2, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0xFFFF", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "channel mask", + "name": "ProductName", "code": 3, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x07FFF800", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "protocol version", + "name": "ProductID", "code": 4, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x02", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "stack profile", + "name": "UserLabel", "code": 5, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x02", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "startup control", + "name": "Location", "code": 6, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x03", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "trust center address", - "code": 16, + "name": "HardwareVersion", + "code": 7, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": "0x00", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "network key", - "code": 18, + "name": "HardwareVersionString", + "code": 8, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x00000000000000000000000000000000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "use insecure join", - "code": 19, + "name": "SoftwareVersion", + "code": 9, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x01", + "defaultValue": "0x00", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "preconfigured link key", - "code": 20, + "name": "SoftwareVersionString", + "code": 10, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x00000000000000000000000000000000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "network key sequence number", - "code": 21, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "3", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ { - "name": "network key type", - "code": 22, + "name": "ArmFailSafe", + "code": 0, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x05", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "network manager address", - "code": 23, + "name": "SetRegulatoryConfig", + "code": 2, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 0 }, { - "name": "scan attempts", - "code": 32, + "name": "CommissioningComplete", + "code": 4, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x05", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ { - "name": "time between scans", - "code": 33, + "name": "cluster revision", + "code": 65533, "mfgCode": null, - "side": "server", + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0064", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ { - "name": "rejoin interval", - "code": 34, + "name": "ArmFailSafeResponse", + "code": 1, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x003C", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 1, + "outgoing": 1 }, { - "name": "max rejoin interval", - "code": 35, + "name": "SetRegulatoryConfigResponse", + "code": 3, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0E10", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 0, + "outgoing": 1 }, { - "name": "indirect poll rate", - "code": 48, + "name": "CommissioningCompleteResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "FabricId", + "code": 0, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "o", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "parent retry threshold", - "code": 49, + "name": "Breadcrumb", + "code": 1, "mfgCode": null, "side": "server", "included": 1, @@ -824,460 +796,41 @@ "reportableChange": 0 }, { - "name": "concentrator flag", - "code": 64, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ { - "name": "concentrator radius", - "code": 65, + "name": "ScanNetworks", + "code": 0, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0F", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "concentrator discovery time", - "code": 66, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x00", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "2", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Basic", - "code": 40, - "mfgCode": null, - "define": "BASIC_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "3", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Basic", - "code": 40, - "mfgCode": null, - "define": "BASIC_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "StartUp", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "ShutDown", - "code": 1, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "Leave", - "code": 2, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - } - ], - "attributes": [ - { - "name": "InteractionModelVersion", - "code": 0, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "VendorName", - "code": 1, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "VendorID", - "code": 2, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductName", - "code": 3, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductID", - "code": 4, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "UserLabel", - "code": 5, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "Location", - "code": 6, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "HardwareVersion", - "code": 7, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "0x00", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "HardwareVersionString", - "code": 8, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "SoftwareVersion", - "code": 9, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "0x00", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "SoftwareVersionString", - "code": 10, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 1, - "bounded": 0, - "defaultValue": "3", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "General Commissioning", - "code": 48, - "mfgCode": null, - "define": "GENERAL_COMMISSIONING_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [ - { - "name": "ArmFailSafe", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "SetRegulatoryConfig", - "code": 2, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "CommissioningComplete", - "code": 4, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - } - ], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "General Commissioning", - "code": 48, - "mfgCode": null, - "define": "GENERAL_COMMISSIONING_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "ArmFailSafeResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "SetRegulatoryConfigResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "CommissioningCompleteResponse", - "code": 5, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - } - ], - "attributes": [ - { - "name": "FabricId", - "code": 0, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "o", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "Breadcrumb", - "code": 1, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Network Commissioning", - "code": 49, - "mfgCode": null, - "define": "NETWORK_COMMISSIONING_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [ - { - "name": "ScanNetworks", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "AddWiFiNetwork", - "code": 2, + "name": "AddWiFiNetwork", + "code": 2, "mfgCode": null, "source": "client", "incoming": 1, @@ -1289,326 +842,41 @@ "mfgCode": null, "source": "client", "incoming": 1, - "outgoing": 0 - }, - { - "name": "RemoveNetwork", - "code": 10, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "EnableNetwork", - "code": 12, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "DisableNetwork", - "code": 14, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "GetLastNetworkCommissioningResult", - "code": 16, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - } - ], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Network Commissioning", - "code": 49, - "mfgCode": null, - "define": "NETWORK_COMMISSIONING_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "ScanNetworksResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "AddWiFiNetworkResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "UpdateWiFiNetworkResponse", - "code": 5, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "RemoveNetworkResponse", - "code": 11, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "EnableNetworkResponse", - "code": 13, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "DisableNetworkResponse", - "code": 15, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - } - ], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Diagnostic Logs", - "code": 50, - "mfgCode": null, - "define": "DIAGNOSTIC_LOGS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "RetrieveLogsRequest", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "RetrieveLogsResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 0, - "outgoing": 1 - } - ] - }, - { - "name": "General Diagnostics", - "code": 51, - "mfgCode": null, - "define": "GENERAL_DIAGNOSTICS_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "General Diagnostics", - "code": 51, - "mfgCode": null, - "define": "GENERAL_DIAGNOSTICS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [], - "attributes": [ - { - "name": "NetworkInterfaces", - "code": 0, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "RebootCount", - "code": 1, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Software Diagnostics", - "code": 52, - "mfgCode": null, - "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [ + "outgoing": 0 + }, { - "name": "ResetWatermarks", - "code": 0, + "name": "RemoveNetwork", + "code": 10, "mfgCode": null, "source": "client", - "incoming": 0, + "incoming": 1, "outgoing": 1 - } - ], - "attributes": [ + }, { - "name": "cluster revision", - "code": 65533, + "name": "EnableNetwork", + "code": 12, "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Software Diagnostics", - "code": 52, - "mfgCode": null, - "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [], - "attributes": [ + "source": "client", + "incoming": 1, + "outgoing": 1 + }, { - "name": "CurrentHeapHighWatermark", - "code": 3, + "name": "DisableNetwork", + "code": 14, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000000000000000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "cluster revision", - "code": 65533, + "name": "GetLastNetworkCommissioningResult", + "code": 16, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 1 } - ] - }, - { - "name": "WiFi Network Diagnostics", - "code": 54, - "mfgCode": null, - "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [], + ], "attributes": [ { "name": "cluster revision", @@ -1628,120 +896,59 @@ ] }, { - "name": "WiFi Network Diagnostics", - "code": 54, + "name": "Network Commissioning", + "code": 49, "mfgCode": null, - "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "define": "NETWORK_COMMISSIONING_CLUSTER", "side": "server", "enabled": 1, - "commands": [], - "attributes": [ - { - "name": "bssid", - "code": 0, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, + "commands": [ { - "name": "SecurityType", + "name": "ScanNetworksResponse", "code": 1, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 1, + "outgoing": 1 }, { - "name": "WiFiVersion", - "code": 2, + "name": "AddWiFiNetworkResponse", + "code": 3, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 0, + "outgoing": 1 }, { - "name": "ChannelNumber", - "code": 3, + "name": "UpdateWiFiNetworkResponse", + "code": 5, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 0, + "outgoing": 1 }, { - "name": "Rssi", - "code": 4, + "name": "RemoveNetworkResponse", + "code": 11, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x00", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 1, + "outgoing": 1 }, { - "name": "cluster revision", - "code": 65533, + "name": "EnableNetworkResponse", + "code": 13, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Ethernet Network Diagnostics", - "code": 55, - "mfgCode": null, - "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [ + "source": "server", + "incoming": 1, + "outgoing": 1 + }, { - "name": "ResetCounts", - "code": 0, + "name": "DisableNetworkResponse", + "code": 15, "mfgCode": null, - "source": "client", - "incoming": 0, + "source": "server", + "incoming": 1, "outgoing": 1 } ], @@ -1750,7 +957,7 @@ "name": "cluster revision", "code": 65533, "mfgCode": null, - "side": "client", + "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, @@ -1764,84 +971,84 @@ ] }, { - "name": "Ethernet Network Diagnostics", - "code": 55, + "name": "Diagnostic Logs", + "code": 50, "mfgCode": null, - "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [], - "attributes": [ - { - "name": "PacketRxCount", - "code": 2, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000000000000000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "PacketTxCount", - "code": 3, - "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000000000000000", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ { - "name": "TxErrCount", - "code": 4, + "name": "RetrieveLogsRequest", + "code": 0, "mfgCode": null, - "side": "server", + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ { - "name": "CollisionCount", - "code": 5, + "name": "NetworkInterfaces", + "code": 0, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "OverrunCount", - "code": 6, + "name": "RebootCount", + "code": 1, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -1865,76 +1072,20 @@ ] }, { - "name": "Operational Credentials", - "code": 62, + "name": "Software Diagnostics", + "code": 52, "mfgCode": null, - "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", "side": "client", "enabled": 0, "commands": [ { - "name": "SetFabric", + "name": "ResetWatermarks", "code": 0, "mfgCode": null, "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "OpCSRRequest", - "code": 4, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "AddNOC", - "code": 6, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "UpdateFabricLabel", - "code": 9, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "RemoveFabric", - "code": 10, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "RemoveAllFabrics", - "code": 11, - "mfgCode": null, - "source": "client", - "incoming": 1, + "incoming": 0, "outgoing": 1 - }, - { - "name": "AddTrustedRootCertificate", - "code": 161, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "RemoveTrustedRootCertificate", - "code": 162, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 } ], "attributes": [ @@ -1956,49 +1107,24 @@ ] }, { - "name": "Operational Credentials", - "code": 62, + "name": "Software Diagnostics", + "code": 52, "mfgCode": null, - "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", "side": "server", "enabled": 1, - "commands": [ - { - "name": "SetFabricResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "OpCSRResponse", - "code": 5, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "NOCResponse", - "code": 8, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - } - ], + "commands": [], "attributes": [ { - "name": "fabrics list", - "code": 1, + "name": "CurrentHeapHighWatermark", + "code": 3, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0000000000000000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -2020,20 +1146,12 @@ "reportableChange": 0 } ] - } - ] - }, - { - "name": "Anonymous Endpoint Type", - "deviceTypeName": "CBA-tempsensor", - "deviceTypeCode": 770, - "deviceTypeProfileId": 261, - "clusters": [ + }, { - "name": "Power Configuration", - "code": 1, + "name": "WiFi Network Diagnostics", + "code": 54, "mfgCode": null, - "define": "POWER_CONFIG_CLUSTER", + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", "side": "client", "enabled": 0, "commands": [], @@ -2045,9 +1163,9 @@ "side": "client", "included": 1, "storageOption": "RAM", - "singleton": 1, + "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -2056,106 +1174,84 @@ ] }, { - "name": "Power Configuration", - "code": 1, + "name": "WiFi Network Diagnostics", + "code": 54, "mfgCode": null, - "define": "POWER_CONFIG_CLUSTER", + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", "side": "server", - "enabled": 0, + "enabled": 1, "commands": [], "attributes": [ { - "name": "battery percentage remaining", - "code": 33, + "name": "bssid", + "code": 0, "mfgCode": null, "side": "server", - "included": 0, + "included": 1, "storageOption": "RAM", - "singleton": 1, + "singleton": 0, "bounded": 0, - "defaultValue": "0x00", - "reportable": 1, + "defaultValue": "", + "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "battery alarm state", - "code": 62, + "name": "SecurityType", + "code": 1, "mfgCode": null, "side": "server", - "included": 0, + "included": 1, "storageOption": "RAM", - "singleton": 1, + "singleton": 0, "bounded": 0, - "defaultValue": "0x00000000", - "reportable": 1, + "defaultValue": "", + "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "cluster revision", - "code": 65533, + "name": "WiFiVersion", + "code": 2, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 1, + "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Device Temperature Configuration", - "code": 2, - "mfgCode": null, - "define": "DEVICE_TEMP_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [], - "attributes": [ + }, { - "name": "cluster revision", - "code": 65533, + "name": "ChannelNumber", + "code": 3, "mfgCode": null, - "side": "client", + "side": "server", "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Device Temperature Configuration", - "code": 2, - "mfgCode": null, - "define": "DEVICE_TEMP_CLUSTER", - "side": "server", - "enabled": 0, - "commands": [], - "attributes": [ + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, { - "name": "current temperature", - "code": 0, + "name": "Rssi", + "code": 4, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x00", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -2179,27 +1275,19 @@ ] }, { - "name": "Identify", - "code": 3, + "name": "Ethernet Network Diagnostics", + "code": 55, "mfgCode": null, - "define": "IDENTIFY_CLUSTER", + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", "side": "client", "enabled": 0, "commands": [ { - "name": "Identify", + "name": "ResetCounts", "code": 0, "mfgCode": null, "source": "client", - "incoming": 1, - "outgoing": 1 - }, - { - "name": "IdentifyQuery", - "code": 1, - "mfgCode": null, - "source": "client", - "incoming": 1, + "incoming": 0, "outgoing": 1 } ], @@ -2213,7 +1301,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -2222,182 +1310,84 @@ ] }, { - "name": "Identify", - "code": 3, + "name": "Ethernet Network Diagnostics", + "code": 55, "mfgCode": null, - "define": "IDENTIFY_CLUSTER", + "define": "ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER", "side": "server", - "enabled": 0, - "commands": [ - { - "name": "IdentifyQueryResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 1 - } - ], + "enabled": 1, + "commands": [], "attributes": [ { - "name": "identify time", - "code": 0, + "name": "PacketRxCount", + "code": 2, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "0x0000000000000000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "cluster revision", - "code": 65533, + "name": "PacketTxCount", + "code": 3, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "0x0000000000000000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Groups", - "code": 4, - "mfgCode": null, - "define": "GROUPS_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [ - { - "name": "AddGroup", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "ViewGroup", - "code": 1, - "mfgCode": null, - "source": "client", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "GetGroupMembership", - "code": 2, - "mfgCode": null, - "source": "client", - "incoming": 0, - "outgoing": 1 - }, - { - "name": "RemoveGroup", - "code": 3, - "mfgCode": null, - "source": "client", - "incoming": 0, - "outgoing": 1 }, { - "name": "RemoveAllGroups", + "name": "TxErrCount", "code": 4, "mfgCode": null, - "source": "client", - "incoming": 0, - "outgoing": 1 + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 }, { - "name": "AddGroupIfIdentifying", + "name": "CollisionCount", "code": 5, "mfgCode": null, - "source": "client", - "incoming": 0, - "outgoing": 1 - } - ], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "client", + "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "3", + "defaultValue": "0x0000000000000000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Groups", - "code": 4, - "mfgCode": null, - "define": "GROUPS_CLUSTER", - "side": "server", - "enabled": 0, - "commands": [ - { - "name": "AddGroupResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "ViewGroupResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "GetGroupMembershipResponse", - "code": 2, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 0 }, { - "name": "RemoveGroupResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "incoming": 1, - "outgoing": 0 - } - ], - "attributes": [ - { - "name": "name support", - "code": 0, + "name": "OverrunCount", + "code": 6, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0000000000000000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -2412,7 +1402,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "3", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -2421,62 +1411,35 @@ ] }, { - "name": "Alarms", - "code": 9, + "name": "AdministratorCommissioning", + "code": 60, "mfgCode": null, - "define": "ALARM_CLUSTER", + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", "side": "client", "enabled": 0, "commands": [ { - "name": "ResetAlarm", + "name": "OpenCommissioningWindow", "code": 0, "mfgCode": null, "source": "client", "incoming": 1, - "outgoing": 0 + "outgoing": 1 }, { - "name": "ResetAllAlarms", + "name": "OpenBasicCommissioningWindow", "code": 1, "mfgCode": null, "source": "client", "incoming": 1, - "outgoing": 0 - } - ], - "attributes": [ - { - "name": "cluster revision", - "code": 65533, - "mfgCode": null, - "side": "client", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0001", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Alarms", - "code": 9, - "mfgCode": null, - "define": "ALARM_CLUSTER", - "side": "server", - "enabled": 0, - "commands": [ + "outgoing": 1 + }, { - "name": "Alarm", - "code": 0, + "name": "RevokeCommissioning", + "code": 2, "mfgCode": null, - "source": "server", - "incoming": 0, + "source": "client", + "incoming": 1, "outgoing": 1 } ], @@ -2485,7 +1448,7 @@ "name": "cluster revision", "code": 65533, "mfgCode": null, - "side": "server", + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, @@ -2499,41 +1462,24 @@ ] }, { - "name": "Commissioning", - "code": 21, + "name": "AdministratorCommissioning", + "code": 60, "mfgCode": null, - "define": "COMMISSIONING_CLUSTER", - "side": "client", - "enabled": 0, - "commands": [ - { - "name": "RestartDevice", - "code": 0, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - }, - { - "name": "ResetStartupParameters", - "code": 3, - "mfgCode": null, - "source": "client", - "incoming": 1, - "outgoing": 0 - } - ], + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], "attributes": [ { "name": "cluster revision", "code": 65533, "mfgCode": null, - "side": "client", + "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -2542,392 +1488,622 @@ ] }, { - "name": "Commissioning", - "code": 21, + "name": "Operational Credentials", + "code": 62, "mfgCode": null, - "define": "COMMISSIONING_CLUSTER", - "side": "server", + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "client", "enabled": 0, "commands": [ { - "name": "RestartDeviceResponse", + "name": "SetFabric", "code": 0, "mfgCode": null, - "source": "server", - "incoming": 0, + "source": "client", + "incoming": 1, "outgoing": 1 }, { - "name": "SaveStartupParametersResponse", - "code": 1, + "name": "OpCSRRequest", + "code": 4, "mfgCode": null, - "source": "server", - "incoming": 0, + "source": "client", + "incoming": 1, "outgoing": 1 }, { - "name": "RestoreStartupParametersResponse", - "code": 2, + "name": "AddNOC", + "code": 6, "mfgCode": null, - "source": "server", - "incoming": 0, + "source": "client", + "incoming": 1, "outgoing": 1 }, { - "name": "ResetStartupParametersResponse", - "code": 3, + "name": "UpdateFabricLabel", + "code": 9, "mfgCode": null, - "source": "server", - "incoming": 0, + "source": "client", + "incoming": 1, "outgoing": 1 - } - ], - "attributes": [ + }, { - "name": "short address", - "code": 0, + "name": "RemoveFabric", + "code": 10, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0xFFFF", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "extended pan id", - "code": 1, + "name": "RemoveAllFabrics", + "code": 11, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0xFFFFFFFFFFFFFFFF", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "pan id", - "code": 2, + "name": "AddTrustedRootCertificate", + "code": 161, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0xFFFF", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 1, + "outgoing": 0 }, { - "name": "channel mask", - "code": 3, + "name": "RemoveTrustedRootCertificate", + "code": 162, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x07FFF800", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ { - "name": "protocol version", - "code": 4, + "name": "cluster revision", + "code": 65533, "mfgCode": null, - "side": "server", + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x02", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "SetFabricResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 }, { - "name": "stack profile", + "name": "OpCSRResponse", "code": 5, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x02", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "server", + "incoming": 1, + "outgoing": 1 }, { - "name": "startup control", - "code": 6, + "name": "NOCResponse", + "code": 8, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "fabrics list", + "code": 1, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x03", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "trust center address", - "code": 16, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + } + ] + }, + { + "name": "Anonymous Endpoint Type", + "deviceTypeName": null, + "deviceTypeCode": null, + "deviceTypeProfileId": null, + "clusters": [ + { + "name": "Power Configuration", + "code": 1, + "mfgCode": null, + "define": "POWER_CONFIG_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ { - "name": "network key", - "code": 18, + "name": "cluster revision", + "code": 65533, "mfgCode": null, - "side": "server", + "side": "client", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x00000000000000000000000000000000", + "defaultValue": "2", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Power Configuration", + "code": 1, + "mfgCode": null, + "define": "POWER_CONFIG_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [], + "attributes": [ { - "name": "use insecure join", - "code": 19, + "name": "battery percentage remaining", + "code": 33, "mfgCode": null, "side": "server", - "included": 1, + "included": 0, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x01", - "reportable": 0, + "defaultValue": "0x00", + "reportable": 1, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "preconfigured link key", - "code": 20, + "name": "battery alarm state", + "code": 62, "mfgCode": null, "side": "server", - "included": 1, + "included": 0, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x00000000000000000000000000000000", - "reportable": 0, + "defaultValue": "0x00000000", + "reportable": 1, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "network key sequence number", - "code": 21, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "2", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Device Temperature Configuration", + "code": 2, + "mfgCode": null, + "define": "DEVICE_TEMP_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [ { - "name": "network key type", - "code": 22, + "name": "cluster revision", + "code": 65533, "mfgCode": null, - "side": "server", + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x05", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Device Temperature Configuration", + "code": 2, + "mfgCode": null, + "define": "DEVICE_TEMP_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [], + "attributes": [ { - "name": "network manager address", - "code": 23, + "name": "current temperature", + "code": 0, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "scan attempts", - "code": 32, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x05", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 }, { - "name": "time between scans", - "code": 33, + "name": "IdentifyQuery", + "code": 1, "mfgCode": null, - "side": "server", + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0064", + "defaultValue": "2", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "IdentifyQueryResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ { - "name": "rejoin interval", - "code": 34, + "name": "identify time", + "code": 0, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x003C", + "defaultValue": "0x0000", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "max rejoin interval", - "code": 35, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0E10", + "defaultValue": "2", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "AddGroup", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 }, { - "name": "indirect poll rate", - "code": 48, + "name": "ViewGroup", + "code": 1, "mfgCode": null, - "side": "server", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 0, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "source": "client", + "incoming": 0, + "outgoing": 1 }, { - "name": "parent retry threshold", - "code": 49, + "name": "GetGroupMembership", + "code": 2, "mfgCode": null, - "side": "server", + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveGroup", + "code": 3, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RemoveAllGroups", + "code": 4, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "AddGroupIfIdentifying", + "code": 5, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "3", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 + } + ] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 }, { - "name": "concentrator flag", - "code": 64, + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "name support", + "code": 0, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 }, { - "name": "concentrator radius", - "code": 65, + "name": "cluster revision", + "code": 65533, "mfgCode": null, "side": "server", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x0F", + "defaultValue": "3", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 + } + ] + }, + { + "name": "Alarms", + "code": 9, + "mfgCode": null, + "define": "ALARM_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "ResetAlarm", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 }, { - "name": "concentrator discovery time", - "code": 66, + "name": "ResetAllAlarms", + "code": 1, "mfgCode": null, - "side": "server", + "source": "client", + "incoming": 1, + "outgoing": 0 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0x00", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Alarms", + "code": 9, + "mfgCode": null, + "define": "ALARM_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [ + { + "name": "Alarm", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ { "name": "cluster revision", "code": 65533, @@ -2937,7 +2113,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "0x0001", "reportable": 0, "minInterval": 0, "maxInterval": 65344, @@ -3187,7 +2363,7 @@ } ] }, - { + { "name": "Temperature Measurement", "code": 1026, "mfgCode": null, @@ -3196,7 +2372,7 @@ "enabled": 0, "commands": [], "attributes": [ - { + { "name": "cluster revision", "code": 65533, "mfgCode": null, @@ -3205,14 +2381,14 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "3", + "defaultValue": "3", "reportable": 0, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, + } + ] + }, { "name": "Temperature Measurement", "code": 1026, @@ -3323,4 +2499,4 @@ } ], "log": [] -} +} \ No newline at end of file diff --git a/examples/thermostat/thermostat-common/gen/IMClusterCommandHandler.cpp b/examples/thermostat/thermostat-common/gen/IMClusterCommandHandler.cpp index 7f77931cfc338c..475e34e1f6f3dd 100644 --- a/examples/thermostat/thermostat-common/gen/IMClusterCommandHandler.cpp +++ b/examples/thermostat/thermostat-common/gen/IMClusterCommandHandler.cpp @@ -51,6 +51,203 @@ void ReportCommandUnsupported(Command * aCommandObj, EndpointId aEndpointId, Clu namespace clusters { +namespace AdministratorCommissioning { + +void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, + TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case Clusters::AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow: { + expectArgumentCount = 1; + uint16_t CommissioningTimeout; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(aEndpointId, apCommandObj, + CommissioningTimeout); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow: { + expectArgumentCount = 6; + uint16_t CommissioningTimeout; + chip::ByteSpan PAKEVerifier; + uint16_t Discriminator; + uint32_t Iterations; + chip::ByteSpan Salt; + uint16_t PasscodeID; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + PAKEVerifier = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: + TLVUnpackError = aDataTlv.Get(Discriminator); + break; + case 3: + TLVUnpackError = aDataTlv.Get(Iterations); + break; + case 4: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + Salt = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 5: + TLVUnpackError = aDataTlv.Get(PasscodeID); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( + aEndpointId, apCommandObj, CommissioningTimeout, PAKEVerifier, Discriminator, Iterations, Salt, PasscodeID); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::RevokeCommissioning: { + + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(aEndpointId, apCommandObj); + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::AdministratorCommissioning::Id, aCommandId); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + Clusters::AdministratorCommissioning::Id, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT + ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError), + ChipError::FormatError(TLVUnpackError), currentDecodeTagId); + // A command with no arguments would never write currentDecodeTagId. If + // progress logging is also disabled, it would look unused. Silence that + // warning. + UNUSED_VAR(currentDecodeTagId); + } +} + +} // namespace AdministratorCommissioning + namespace BarrierControl { void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, @@ -6380,6 +6577,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case Clusters::AdministratorCommissioning::Id: + clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case Clusters::BarrierControl::Id: clusters::BarrierControl::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/thermostat/thermostat-common/gen/callback-stub.cpp b/examples/thermostat/thermostat-common/gen/callback-stub.cpp index f110aa66df747a..3e2fd72325035e 100644 --- a/examples/thermostat/thermostat-common/gen/callback-stub.cpp +++ b/examples/thermostat/thermostat-common/gen/callback-stub.cpp @@ -31,6 +31,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_ACCOUNT_LOGIN_CLUSTER_ID: emberAfAccountLoginClusterInitCallback(endpoint); break; + case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID: + emberAfAdministratorCommissioningClusterInitCallback(endpoint); + break; case ZCL_APPLICATION_BASIC_CLUSTER_ID: emberAfApplicationBasicClusterInitCallback(endpoint); break; @@ -180,6 +183,11 @@ void __attribute__((weak)) emberAfAccountLoginClusterInitCallback(EndpointId end // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfApplicationBasicClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/thermostat/thermostat-common/gen/endpoint_config.h b/examples/thermostat/thermostat-common/gen/endpoint_config.h index 6e11cbbd448c8e..5b436216acd4ca 100644 --- a/examples/thermostat/thermostat-common/gen/endpoint_config.h +++ b/examples/thermostat/thermostat-common/gen/endpoint_config.h @@ -1803,7 +1803,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 340 +#define GENERATED_ATTRIBUTE_COUNT 341 #define GENERATED_ATTRIBUTES \ { \ \ @@ -1949,6 +1949,9 @@ { 0x0006, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(2712) }, /* OverrunCount */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0001, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(2720) }, /* fabrics list */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ @@ -2308,7 +2311,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 51 +#define GENERATED_CLUSTER_COUNT 52 #define GENERATED_CLUSTERS \ { \ { \ @@ -2348,152 +2351,155 @@ 0x0037, ZAP_ATTRIBUTE_INDEX(108), 6, 42, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { \ - 0x003E, ZAP_ATTRIBUTE_INDEX(114), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x003C, ZAP_ATTRIBUTE_INDEX(114), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { \ + 0x003E, ZAP_ATTRIBUTE_INDEX(115), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { \ - 0x0405, ZAP_ATTRIBUTE_INDEX(116), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0405, ZAP_ATTRIBUTE_INDEX(117), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Relative Humidity Measurement (server) */ \ { \ - 0xF000, ZAP_ATTRIBUTE_INDEX(120), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0xF000, ZAP_ATTRIBUTE_INDEX(121), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Binding (server) */ \ { \ - 0xF004, ZAP_ATTRIBUTE_INDEX(121), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0xF004, ZAP_ATTRIBUTE_INDEX(122), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Group Key Management (server) */ \ { 0x0003, \ - ZAP_ATTRIBUTE_INDEX(124), \ + ZAP_ATTRIBUTE_INDEX(125), \ 2, \ 4, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayIdentifyServer }, /* Endpoint: 1, Cluster: Identify (server) */ \ { 0x0004, \ - ZAP_ATTRIBUTE_INDEX(126), \ + ZAP_ATTRIBUTE_INDEX(127), \ 2, \ 3, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayGroupsServer }, /* Endpoint: 1, Cluster: Groups (server) */ \ { 0x0005, \ - ZAP_ATTRIBUTE_INDEX(128), \ + ZAP_ATTRIBUTE_INDEX(129), \ 6, \ 8, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayScenesServer }, /* Endpoint: 1, Cluster: Scenes (server) */ \ { 0x0006, \ - ZAP_ATTRIBUTE_INDEX(134), \ + ZAP_ATTRIBUTE_INDEX(135), \ 7, \ 13, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOnOffServer }, /* Endpoint: 1, Cluster: On/off (server) */ \ { 0x0008, \ - ZAP_ATTRIBUTE_INDEX(141), \ + ZAP_ATTRIBUTE_INDEX(142), \ 2, \ 3, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayLevelControlServer }, /* Endpoint: 1, Cluster: Level Control (server) */ \ { \ - 0x000F, ZAP_ATTRIBUTE_INDEX(143), 4, 5, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x000F, ZAP_ATTRIBUTE_INDEX(144), 4, 5, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Binary Input (Basic) (server) */ \ { \ - 0x001D, ZAP_ATTRIBUTE_INDEX(147), 5, 1018, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x001D, ZAP_ATTRIBUTE_INDEX(148), 5, 1018, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Descriptor (server) */ \ { \ - 0x0039, ZAP_ATTRIBUTE_INDEX(152), 15, 855, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0039, ZAP_ATTRIBUTE_INDEX(153), 15, 855, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Bridged Device Basic (server) */ \ { \ - 0x003B, ZAP_ATTRIBUTE_INDEX(167), 3, 4, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x003B, ZAP_ATTRIBUTE_INDEX(168), 3, 4, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Switch (server) */ \ { \ - 0x0040, ZAP_ATTRIBUTE_INDEX(170), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0040, ZAP_ATTRIBUTE_INDEX(171), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Fixed Label (server) */ \ { 0x0101, \ - ZAP_ATTRIBUTE_INDEX(172), \ + ZAP_ATTRIBUTE_INDEX(173), \ 4, \ 5, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayDoorLockServer }, /* Endpoint: 1, Cluster: Door Lock (server) */ \ { \ - 0x0102, ZAP_ATTRIBUTE_INDEX(176), 19, 31, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0102, ZAP_ATTRIBUTE_INDEX(177), 19, 31, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Window Covering (server) */ \ { \ - 0x0103, ZAP_ATTRIBUTE_INDEX(195), 5, 7, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0103, ZAP_ATTRIBUTE_INDEX(196), 5, 7, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Barrier Control (server) */ \ { \ - 0x0201, ZAP_ATTRIBUTE_INDEX(200), 10, 17, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0201, ZAP_ATTRIBUTE_INDEX(201), 10, 17, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Thermostat (server) */ \ { 0x0300, \ - ZAP_ATTRIBUTE_INDEX(210), \ + ZAP_ATTRIBUTE_INDEX(211), \ 51, \ 336, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayColorControlServer }, /* Endpoint: 1, Cluster: Color Control (server) */ \ { \ - 0x0402, ZAP_ATTRIBUTE_INDEX(261), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0402, ZAP_ATTRIBUTE_INDEX(262), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Temperature Measurement (server) */ \ { \ - 0x0403, ZAP_ATTRIBUTE_INDEX(265), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0403, ZAP_ATTRIBUTE_INDEX(266), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Pressure Measurement (server) */ \ { \ - 0x0404, ZAP_ATTRIBUTE_INDEX(269), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0404, ZAP_ATTRIBUTE_INDEX(270), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Flow Measurement (server) */ \ { \ - 0x0405, ZAP_ATTRIBUTE_INDEX(273), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0405, ZAP_ATTRIBUTE_INDEX(274), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Relative Humidity Measurement (server) */ \ { 0x0500, \ - ZAP_ATTRIBUTE_INDEX(277), \ + ZAP_ATTRIBUTE_INDEX(278), \ 6, \ 16, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION) | \ ZAP_CLUSTER_MASK(MESSAGE_SENT_FUNCTION), \ chipFuncArrayIasZoneServer }, /* Endpoint: 1, Cluster: IAS Zone (server) */ \ { \ - 0x0503, ZAP_ATTRIBUTE_INDEX(283), 2, 34, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0503, ZAP_ATTRIBUTE_INDEX(284), 2, 34, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Wake on LAN (server) */ \ { \ - 0x0504, ZAP_ATTRIBUTE_INDEX(285), 4, 320, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0504, ZAP_ATTRIBUTE_INDEX(286), 4, 320, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: TV Channel (server) */ \ { \ - 0x0505, ZAP_ATTRIBUTE_INDEX(289), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0505, ZAP_ATTRIBUTE_INDEX(290), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Target Navigator (server) */ \ { \ - 0x0506, ZAP_ATTRIBUTE_INDEX(291), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0506, ZAP_ATTRIBUTE_INDEX(292), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Media Playback (server) */ \ { \ - 0x0507, ZAP_ATTRIBUTE_INDEX(292), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0507, ZAP_ATTRIBUTE_INDEX(293), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Media Input (server) */ \ { \ - 0x0508, ZAP_ATTRIBUTE_INDEX(294), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0508, ZAP_ATTRIBUTE_INDEX(295), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Low Power (server) */ \ { \ - 0x0509, ZAP_ATTRIBUTE_INDEX(295), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0509, ZAP_ATTRIBUTE_INDEX(296), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Keypad Input (server) */ \ { \ - 0x050A, ZAP_ATTRIBUTE_INDEX(296), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050A, ZAP_ATTRIBUTE_INDEX(297), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Content Launcher (server) */ \ { \ - 0x050B, ZAP_ATTRIBUTE_INDEX(299), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050B, ZAP_ATTRIBUTE_INDEX(300), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Audio Output (server) */ \ { \ - 0x050C, ZAP_ATTRIBUTE_INDEX(301), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050C, ZAP_ATTRIBUTE_INDEX(302), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Application Launcher (server) */ \ { \ - 0x050D, ZAP_ATTRIBUTE_INDEX(303), 8, 105, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050D, ZAP_ATTRIBUTE_INDEX(304), 8, 105, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Application Basic (server) */ \ { \ - 0x050E, ZAP_ATTRIBUTE_INDEX(311), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050E, ZAP_ATTRIBUTE_INDEX(312), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Account Login (server) */ \ { \ - 0x050F, ZAP_ATTRIBUTE_INDEX(312), 21, 1579, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050F, ZAP_ATTRIBUTE_INDEX(313), 21, 1579, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Test Cluster (server) */ \ { \ - 0xF000, ZAP_ATTRIBUTE_INDEX(333), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0xF000, ZAP_ATTRIBUTE_INDEX(334), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Binding (server) */ \ { 0x0006, \ - ZAP_ATTRIBUTE_INDEX(334), \ + ZAP_ATTRIBUTE_INDEX(335), \ 2, \ 3, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOnOffServer }, /* Endpoint: 2, Cluster: On/off (server) */ \ { 0x0406, \ - ZAP_ATTRIBUTE_INDEX(336), \ + ZAP_ATTRIBUTE_INDEX(337), \ 4, \ 5, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ @@ -2505,7 +2511,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 15, 3560 }, { ZAP_CLUSTER_INDEX(15), 34, 6195 }, { ZAP_CLUSTER_INDEX(49), 2, 8 }, \ + { ZAP_CLUSTER_INDEX(0), 16, 3562 }, { ZAP_CLUSTER_INDEX(16), 34, 6195 }, { ZAP_CLUSTER_INDEX(50), 2, 8 }, \ } // Largest attribute size is needed for various buffers @@ -2515,7 +2521,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (1497) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (9763) +#define ATTRIBUTE_MAX_SIZE (9765) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (3) @@ -2559,7 +2565,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (200) +#define EMBER_AF_GENERATED_COMMAND_COUNT (203) #define GENERATED_COMMANDS \ { \ \ @@ -2613,6 +2619,11 @@ /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { 0x0037, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetCounts */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0x003C, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenCommissioningWindow */ \ + { 0x003C, 0x01, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenBasicCommissioningWindow */ \ + { 0x003C, 0x02, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RevokeCommissioning */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x003E, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* SetFabric */ \ { 0x003E, 0x01, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* SetFabricResponse */ \ diff --git a/examples/thermostat/thermostat-common/gen/gen_config.h b/examples/thermostat/thermostat-common/gen/gen_config.h index 7dc1dfe680b920..5635c2e018b909 100644 --- a/examples/thermostat/thermostat-common/gen/gen_config.h +++ b/examples/thermostat/thermostat-common/gen/gen_config.h @@ -30,6 +30,7 @@ /**** Cluster endpoint counts ****/ #define EMBER_AF_ACCOUNT_LOGIN_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_APPLICATION_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_APPLICATION_LAUNCHER_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_AUDIO_OUTPUT_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -84,6 +85,11 @@ #define EMBER_AF_PLUGIN_ACCOUNT_LOGIN_SERVER #define EMBER_AF_PLUGIN_ACCOUNT_LOGIN +// Use this macro to check if the server side of the AdministratorCommissioning cluster is included +#define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING + // Use this macro to check if the server side of the Application Basic cluster is included #define ZCL_USING_APPLICATION_BASIC_CLUSTER_SERVER #define EMBER_AF_PLUGIN_APPLICATION_BASIC_SERVER diff --git a/examples/thermostat/thermostat-common/thermostat.zap b/examples/thermostat/thermostat-common/thermostat.zap index ec96a791248996..9d9cccf55afd1f 100644 --- a/examples/thermostat/thermostat-common/thermostat.zap +++ b/examples/thermostat/thermostat-common/thermostat.zap @@ -3187,6 +3187,83 @@ } ] }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "Operational Credentials", "code": 62, diff --git a/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp b/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp index 33a9053f53aab4..52a8e75efd969d 100644 --- a/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp +++ b/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp @@ -224,6 +224,203 @@ void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aComman } // namespace AccountLogin +namespace AdministratorCommissioning { + +void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, + TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case Clusters::AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow: { + expectArgumentCount = 1; + uint16_t CommissioningTimeout; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(aEndpointId, apCommandObj, + CommissioningTimeout); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow: { + expectArgumentCount = 6; + uint16_t CommissioningTimeout; + chip::ByteSpan PAKEVerifier; + uint16_t Discriminator; + uint32_t Iterations; + chip::ByteSpan Salt; + uint16_t PasscodeID; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + PAKEVerifier = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: + TLVUnpackError = aDataTlv.Get(Discriminator); + break; + case 3: + TLVUnpackError = aDataTlv.Get(Iterations); + break; + case 4: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + Salt = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 5: + TLVUnpackError = aDataTlv.Get(PasscodeID); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( + aEndpointId, apCommandObj, CommissioningTimeout, PAKEVerifier, Discriminator, Iterations, Salt, PasscodeID); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::RevokeCommissioning: { + + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(aEndpointId, apCommandObj); + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::AdministratorCommissioning::Id, aCommandId); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + Clusters::AdministratorCommissioning::Id, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT + ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError), + ChipError::FormatError(TLVUnpackError), currentDecodeTagId); + // A command with no arguments would never write currentDecodeTagId. If + // progress logging is also disabled, it would look unused. Silence that + // warning. + UNUSED_VAR(currentDecodeTagId); + } +} + +} // namespace AdministratorCommissioning + namespace ApplicationBasic { void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, @@ -4305,6 +4502,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC case Clusters::AccountLogin::Id: clusters::AccountLogin::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; + case Clusters::AdministratorCommissioning::Id: + clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case Clusters::ApplicationBasic::Id: clusters::ApplicationBasic::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/tv-app/tv-common/gen/callback-stub.cpp b/examples/tv-app/tv-common/gen/callback-stub.cpp index 5650d1ec7716ca..00eb783915df3d 100644 --- a/examples/tv-app/tv-common/gen/callback-stub.cpp +++ b/examples/tv-app/tv-common/gen/callback-stub.cpp @@ -31,6 +31,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_ACCOUNT_LOGIN_CLUSTER_ID: emberAfAccountLoginClusterInitCallback(endpoint); break; + case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID: + emberAfAdministratorCommissioningClusterInitCallback(endpoint); + break; case ZCL_APPLICATION_BASIC_CLUSTER_ID: emberAfApplicationBasicClusterInitCallback(endpoint); break; @@ -126,6 +129,11 @@ void __attribute__((weak)) emberAfAccountLoginClusterInitCallback(EndpointId end // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfApplicationBasicClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/tv-app/tv-common/gen/endpoint_config.h b/examples/tv-app/tv-common/gen/endpoint_config.h index c293ded0cbf366..8872f616467b12 100644 --- a/examples/tv-app/tv-common/gen/endpoint_config.h +++ b/examples/tv-app/tv-common/gen/endpoint_config.h @@ -1391,7 +1391,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 185 +#define GENERATED_ATTRIBUTE_COUNT 186 #define GENERATED_ATTRIBUTES \ { \ \ @@ -1529,6 +1529,9 @@ { 0x0006, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(2680) }, /* OverrunCount */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0001, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(2688) }, /* fabrics list */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ @@ -1671,7 +1674,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 34 +#define GENERATED_CLUSTER_COUNT 35 #define GENERATED_CLUSTERS \ { \ { \ @@ -1711,82 +1714,85 @@ 0x0037, ZAP_ATTRIBUTE_INDEX(100), 6, 42, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { \ - 0x003E, ZAP_ATTRIBUTE_INDEX(106), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x003C, ZAP_ATTRIBUTE_INDEX(106), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { \ + 0x003E, ZAP_ATTRIBUTE_INDEX(107), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { \ - 0x0405, ZAP_ATTRIBUTE_INDEX(108), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0405, ZAP_ATTRIBUTE_INDEX(109), 4, 8, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Relative Humidity Measurement (server) */ \ { \ - 0xF000, ZAP_ATTRIBUTE_INDEX(112), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0xF000, ZAP_ATTRIBUTE_INDEX(113), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Binding (server) */ \ { \ - 0xF004, ZAP_ATTRIBUTE_INDEX(113), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0xF004, ZAP_ATTRIBUTE_INDEX(114), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Group Key Management (server) */ \ { 0x0006, \ - ZAP_ATTRIBUTE_INDEX(116), \ + ZAP_ATTRIBUTE_INDEX(117), \ 2, \ 3, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOnOffServer }, /* Endpoint: 1, Cluster: On/off (server) */ \ { \ - 0x0503, ZAP_ATTRIBUTE_INDEX(118), 2, 34, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0503, ZAP_ATTRIBUTE_INDEX(119), 2, 34, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Wake on LAN (server) */ \ { \ - 0x0504, ZAP_ATTRIBUTE_INDEX(120), 4, 320, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0504, ZAP_ATTRIBUTE_INDEX(121), 4, 320, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: TV Channel (server) */ \ { \ - 0x0505, ZAP_ATTRIBUTE_INDEX(124), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0505, ZAP_ATTRIBUTE_INDEX(125), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Target Navigator (server) */ \ { \ - 0x0507, ZAP_ATTRIBUTE_INDEX(126), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0507, ZAP_ATTRIBUTE_INDEX(127), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Media Input (server) */ \ { \ - 0x0508, ZAP_ATTRIBUTE_INDEX(129), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0508, ZAP_ATTRIBUTE_INDEX(130), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Low Power (server) */ \ { \ - 0x0509, ZAP_ATTRIBUTE_INDEX(130), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0509, ZAP_ATTRIBUTE_INDEX(131), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Keypad Input (server) */ \ { \ - 0x050A, ZAP_ATTRIBUTE_INDEX(131), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050A, ZAP_ATTRIBUTE_INDEX(132), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Content Launcher (server) */ \ { \ - 0x050C, ZAP_ATTRIBUTE_INDEX(134), 4, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050C, ZAP_ATTRIBUTE_INDEX(135), 4, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Application Launcher (server) */ \ { 0x0006, \ - ZAP_ATTRIBUTE_INDEX(138), \ + ZAP_ATTRIBUTE_INDEX(139), \ 2, \ 3, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOnOffServer }, /* Endpoint: 2, Cluster: On/off (server) */ \ { 0x0008, \ - ZAP_ATTRIBUTE_INDEX(140), \ + ZAP_ATTRIBUTE_INDEX(141), \ 2, \ 3, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayLevelControlServer }, /* Endpoint: 2, Cluster: Level Control (server) */ \ { \ - 0x050B, ZAP_ATTRIBUTE_INDEX(142), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050B, ZAP_ATTRIBUTE_INDEX(143), 3, 257, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 2, Cluster: Audio Output (server) */ \ { \ - 0x0506, ZAP_ATTRIBUTE_INDEX(145), 9, 59, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0506, ZAP_ATTRIBUTE_INDEX(146), 9, 59, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 3, Cluster: Media Playback (server) */ \ { \ - 0x050A, ZAP_ATTRIBUTE_INDEX(154), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050A, ZAP_ATTRIBUTE_INDEX(155), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 3, Cluster: Content Launcher (server) */ \ { \ - 0x050D, ZAP_ATTRIBUTE_INDEX(157), 8, 105, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050D, ZAP_ATTRIBUTE_INDEX(158), 8, 105, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 3, Cluster: Application Basic (server) */ \ { \ - 0x050E, ZAP_ATTRIBUTE_INDEX(165), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050E, ZAP_ATTRIBUTE_INDEX(166), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 3, Cluster: Account Login (server) */ \ { \ - 0x050A, ZAP_ATTRIBUTE_INDEX(166), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050A, ZAP_ATTRIBUTE_INDEX(167), 3, 510, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 4, Cluster: Content Launcher (server) */ \ { \ - 0x050D, ZAP_ATTRIBUTE_INDEX(169), 8, 105, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050D, ZAP_ATTRIBUTE_INDEX(170), 8, 105, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 4, Cluster: Application Basic (server) */ \ { \ - 0x050D, ZAP_ATTRIBUTE_INDEX(177), 8, 105, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x050D, ZAP_ATTRIBUTE_INDEX(178), 8, 105, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 5, Cluster: Application Basic (server) */ \ } @@ -1795,8 +1801,8 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 15, 3527 }, { ZAP_CLUSTER_INDEX(15), 9, 1642 }, { ZAP_CLUSTER_INDEX(24), 3, 263 }, \ - { ZAP_CLUSTER_INDEX(27), 4, 676 }, { ZAP_CLUSTER_INDEX(31), 2, 615 }, { ZAP_CLUSTER_INDEX(33), 1, 105 }, \ + { ZAP_CLUSTER_INDEX(0), 16, 3529 }, { ZAP_CLUSTER_INDEX(16), 9, 1642 }, { ZAP_CLUSTER_INDEX(25), 3, 263 }, \ + { ZAP_CLUSTER_INDEX(28), 4, 676 }, { ZAP_CLUSTER_INDEX(32), 2, 615 }, { ZAP_CLUSTER_INDEX(34), 1, 105 }, \ } // Largest attribute size is needed for various buffers @@ -1806,7 +1812,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (641) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (6828) +#define ATTRIBUTE_MAX_SIZE (6830) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (6) @@ -1850,7 +1856,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (116) +#define EMBER_AF_GENERATED_COMMAND_COUNT (119) #define GENERATED_COMMANDS \ { \ \ @@ -1904,6 +1910,11 @@ /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { 0x0037, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetCounts */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0x003C, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenCommissioningWindow */ \ + { 0x003C, 0x01, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenBasicCommissioningWindow */ \ + { 0x003C, 0x02, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RevokeCommissioning */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x003E, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* SetFabric */ \ { 0x003E, 0x01, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* SetFabricResponse */ \ diff --git a/examples/tv-app/tv-common/gen/gen_config.h b/examples/tv-app/tv-common/gen/gen_config.h index 14990ffa3e5b86..d9f41cd6ac53c7 100644 --- a/examples/tv-app/tv-common/gen/gen_config.h +++ b/examples/tv-app/tv-common/gen/gen_config.h @@ -30,6 +30,7 @@ /**** Cluster endpoint counts ****/ #define EMBER_AF_ACCOUNT_LOGIN_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_APPLICATION_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (3) #define EMBER_AF_APPLICATION_LAUNCHER_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_AUDIO_OUTPUT_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -66,6 +67,11 @@ #define EMBER_AF_PLUGIN_ACCOUNT_LOGIN_SERVER #define EMBER_AF_PLUGIN_ACCOUNT_LOGIN +// Use this macro to check if the server side of the AdministratorCommissioning cluster is included +#define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING + // Use this macro to check if the server side of the Application Basic cluster is included #define ZCL_USING_APPLICATION_BASIC_CLUSTER_SERVER #define EMBER_AF_PLUGIN_APPLICATION_BASIC_SERVER diff --git a/examples/tv-app/tv-common/tv-app.zap b/examples/tv-app/tv-common/tv-app.zap index 253ba03beae286..893dfdc10654f0 100644 --- a/examples/tv-app/tv-common/tv-app.zap +++ b/examples/tv-app/tv-common/tv-app.zap @@ -572,7 +572,7 @@ "commands": [], "attributes": [ { - "name": "on/off", + "name": "OnOff", "code": 0, "mfgCode": null, "side": "server", @@ -3067,6 +3067,83 @@ } ] }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "Operational Credentials", "code": 62, @@ -5910,7 +5987,7 @@ "commands": [], "attributes": [ { - "name": "on/off", + "name": "OnOff", "code": 0, "mfgCode": null, "side": "server", @@ -6770,7 +6847,7 @@ "commands": [], "attributes": [ { - "name": "on/off", + "name": "OnOff", "code": 0, "mfgCode": null, "side": "server", diff --git a/examples/window-app/common/gen/IMClusterCommandHandler.cpp b/examples/window-app/common/gen/IMClusterCommandHandler.cpp index 70e064a40bc914..c06d6589cd0b55 100644 --- a/examples/window-app/common/gen/IMClusterCommandHandler.cpp +++ b/examples/window-app/common/gen/IMClusterCommandHandler.cpp @@ -51,6 +51,203 @@ void ReportCommandUnsupported(Command * aCommandObj, EndpointId aEndpointId, Clu namespace clusters { +namespace AdministratorCommissioning { + +void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, + TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case Clusters::AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow: { + expectArgumentCount = 1; + uint16_t CommissioningTimeout; + bool argExists[1]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 1) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(aEndpointId, apCommandObj, + CommissioningTimeout); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow: { + expectArgumentCount = 6; + uint16_t CommissioningTimeout; + chip::ByteSpan PAKEVerifier; + uint16_t Discriminator; + uint32_t Iterations; + chip::ByteSpan Salt; + uint16_t PasscodeID; + bool argExists[6]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 6) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(CommissioningTimeout); + break; + case 1: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + PAKEVerifier = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 2: + TLVUnpackError = aDataTlv.Get(Discriminator); + break; + case 3: + TLVUnpackError = aDataTlv.Get(Iterations); + break; + case 4: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + Salt = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + case 5: + TLVUnpackError = aDataTlv.Get(PasscodeID); + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount) + { + wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( + aEndpointId, apCommandObj, CommissioningTimeout, PAKEVerifier, Discriminator, Iterations, Salt, PasscodeID); + } + break; + } + case Clusters::AdministratorCommissioning::Commands::Ids::RevokeCommissioning: { + + wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(aEndpointId, apCommandObj); + break; + } + default: { + // Unrecognized command ID, error status will apply. + ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::AdministratorCommissioning::Id, aCommandId); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + Clusters::AdministratorCommissioning::Id, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT + ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError), + ChipError::FormatError(TLVUnpackError), currentDecodeTagId); + // A command with no arguments would never write currentDecodeTagId. If + // progress logging is also disabled, it would look unused. Silence that + // warning. + UNUSED_VAR(currentDecodeTagId); + } +} + +} // namespace AdministratorCommissioning + namespace GeneralCommissioning { void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, @@ -1741,6 +1938,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case Clusters::AdministratorCommissioning::Id: + clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case Clusters::GeneralCommissioning::Id: clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/window-app/common/gen/callback-stub.cpp b/examples/window-app/common/gen/callback-stub.cpp index c35b636e778b0a..7f9a410d6ef5d3 100644 --- a/examples/window-app/common/gen/callback-stub.cpp +++ b/examples/window-app/common/gen/callback-stub.cpp @@ -28,6 +28,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) { switch (clusterId) { + case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID: + emberAfAdministratorCommissioningClusterInitCallback(endpoint); + break; case ZCL_BASIC_CLUSTER_ID: emberAfBasicClusterInitCallback(endpoint); break; @@ -64,6 +67,11 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) } } +void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/window-app/common/gen/endpoint_config.h b/examples/window-app/common/gen/endpoint_config.h index bdc55e8729e21a..71d0ca5538e5c3 100644 --- a/examples/window-app/common/gen/endpoint_config.h +++ b/examples/window-app/common/gen/endpoint_config.h @@ -583,7 +583,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 115 +#define GENERATED_ATTRIBUTE_COUNT 116 #define GENERATED_ATTRIBUTES \ { \ \ @@ -701,6 +701,9 @@ { 0x0006, ZAP_TYPE(INT64U), 8, 0, ZAP_LONG_DEFAULTS_INDEX(1264) }, /* OverrunCount */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x0001, ZAP_TYPE(ARRAY), 254, 0, ZAP_LONG_DEFAULTS_INDEX(1272) }, /* fabrics list */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ @@ -737,7 +740,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 10 +#define GENERATED_CLUSTER_COUNT 11 #define GENERATED_CLUSTERS \ { \ { 0x0028, \ @@ -768,10 +771,13 @@ 0x0037, ZAP_ATTRIBUTE_INDEX(88), 6, 42, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { \ - 0x003E, ZAP_ATTRIBUTE_INDEX(94), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x003C, ZAP_ATTRIBUTE_INDEX(94), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { \ + 0x003E, ZAP_ATTRIBUTE_INDEX(95), 2, 256, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { \ - 0x0102, ZAP_ATTRIBUTE_INDEX(96), 19, 31, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0102, ZAP_ATTRIBUTE_INDEX(97), 19, 31, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Window Covering (server) */ \ } @@ -780,7 +786,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 9, 1586 }, { ZAP_CLUSTER_INDEX(9), 1, 31 }, \ + { ZAP_CLUSTER_INDEX(0), 10, 1588 }, { ZAP_CLUSTER_INDEX(10), 1, 31 }, \ } // Largest attribute size is needed for various buffers @@ -790,7 +796,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (240) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (1617) +#define ATTRIBUTE_MAX_SIZE (1619) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (2) @@ -834,7 +840,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (46) +#define EMBER_AF_GENERATED_COMMAND_COUNT (49) #define GENERATED_COMMANDS \ { \ \ @@ -876,6 +882,11 @@ /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { 0x0037, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetCounts */ \ \ + /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ + { 0x003C, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenCommissioningWindow */ \ + { 0x003C, 0x01, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenBasicCommissioningWindow */ \ + { 0x003C, 0x02, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RevokeCommissioning */ \ + \ /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { 0x003E, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* SetFabric */ \ { 0x003E, 0x01, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* SetFabricResponse */ \ diff --git a/examples/window-app/common/gen/gen_config.h b/examples/window-app/common/gen/gen_config.h index f7e91ddf1f71e8..114f7c7fe7a072 100644 --- a/examples/window-app/common/gen/gen_config.h +++ b/examples/window-app/common/gen/gen_config.h @@ -29,6 +29,7 @@ #define EMBER_APS_UNICAST_MESSAGE_COUNT 10 /**** Cluster endpoint counts ****/ +#define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_GENERAL_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -42,6 +43,11 @@ /**** Cluster Plugins ****/ +// Use this macro to check if the server side of the AdministratorCommissioning cluster is included +#define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_SERVER +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING + // Use this macro to check if the server side of the Basic cluster is included #define ZCL_USING_BASIC_CLUSTER_SERVER #define EMBER_AF_PLUGIN_BASIC_SERVER diff --git a/examples/window-app/common/window-app.zap b/examples/window-app/common/window-app.zap index 462e1a3ab48fba..33df924590ac81 100644 --- a/examples/window-app/common/window-app.zap +++ b/examples/window-app/common/window-app.zap @@ -2448,6 +2448,83 @@ } ] }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "Operational Credentials", "code": 62, diff --git a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp new file mode 100644 index 00000000000000..c95195c1d2a3a8 --- /dev/null +++ b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp @@ -0,0 +1,60 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/**************************************************************************** + * @file + * @brief Implementation for the Administrator Commissioning Cluster + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; + +bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(app::CommandHandler * commandObj, + uint16_t CommissioningTimeout, ByteSpan PAKEVerifier, + uint16_t Discriminator, uint32_t Iterations, + ByteSpan Salt, uint16_t PasscodeID) +{ + EmberAfStatus status = EMBER_ZCL_STATUS_FAILURE; + emberAfSendImmediateDefaultResponse(status); + return true; +} + +bool emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(app::CommandHandler * commandObj, + uint16_t CommissioningTimeout) +{ + EmberAfStatus status = EMBER_ZCL_STATUS_FAILURE; + emberAfSendImmediateDefaultResponse(status); + return true; +} + +bool emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(app::CommandHandler * commandObj) +{ + EmberAfStatus status = EMBER_ZCL_STATUS_FAILURE; + emberAfSendImmediateDefaultResponse(status); + return true; +} diff --git a/src/app/common/gen/attribute-id.h b/src/app/common/gen/attribute-id.h index c7137f8b5958c0..f874231afd0733 100644 --- a/src/app/common/gen/attribute-id.h +++ b/src/app/common/gen/attribute-id.h @@ -464,6 +464,12 @@ #define ZCL_CURRENT_POSITION_ATTRIBUTE_ID (0x0001) #define ZCL_MULTI_PRESS_MAX_ATTRIBUTE_ID (0x0002) +// Attribute ids for cluster: AdministratorCommissioning + +// Client attributes + +// Server attributes + // Attribute ids for cluster: Operational Credentials // Client attributes diff --git a/src/app/common/gen/callback.h b/src/app/common/gen/callback.h index 5f719c72b88fc1..a170292217a522 100644 --- a/src/app/common/gen/callback.h +++ b/src/app/common/gen/callback.h @@ -266,6 +266,14 @@ void emberAfBridgedDeviceBasicClusterInitCallback(chip::EndpointId endpoint); */ void emberAfSwitchClusterInitCallback(chip::EndpointId endpoint); +/** @brief AdministratorCommissioning Cluster Init + * + * Cluster Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfAdministratorCommissioningClusterInitCallback(chip::EndpointId endpoint); + /** @brief Operational Credentials Cluster Init * * Cluster Init @@ -4694,6 +4702,146 @@ void emberAfSwitchClusterServerTickCallback(chip::EndpointId endpoint); */ void emberAfSwitchClusterClientTickCallback(chip::EndpointId endpoint); +// +// AdministratorCommissioning Cluster +// + +/** @brief AdministratorCommissioning Cluster Server Init + * + * Server Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfAdministratorCommissioningClusterServerInitCallback(chip::EndpointId endpoint); + +/** @brief AdministratorCommissioning Cluster Client Init + * + * Client Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfAdministratorCommissioningClusterClientInitCallback(chip::EndpointId endpoint); + +/** @brief AdministratorCommissioning Cluster Server Attribute Changed + * + * Server Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + */ +void emberAfAdministratorCommissioningClusterServerAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId); + +/** @brief AdministratorCommissioning Cluster Client Attribute Changed + * + * Client Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + */ +void emberAfAdministratorCommissioningClusterClientAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId); + +/** @brief AdministratorCommissioning Cluster Server Manufacturer Specific Attribute Changed + * + * Server Manufacturer Specific Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + * @param manufacturerCode Manufacturer Code of the attribute that changed + */ +void emberAfAdministratorCommissioningClusterServerManufacturerSpecificAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + uint16_t manufacturerCode); + +/** @brief AdministratorCommissioning Cluster Client Manufacturer Specific Attribute Changed + * + * Client Manufacturer Specific Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + * @param manufacturerCode Manufacturer Code of the attribute that changed + */ +void emberAfAdministratorCommissioningClusterClientManufacturerSpecificAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + uint16_t manufacturerCode); + +/** @brief AdministratorCommissioning Cluster Server Message Sent + * + * Server Message Sent + * + * @param type The type of message sent + * @param destination The destination to which the message was sent + * @param apsFrame The APS frame for the message + * @param msgLen The length of the message + * @param message The message that was sent + * @param status The status of the sent message + */ +void emberAfAdministratorCommissioningClusterServerMessageSentCallback(const chip::MessageSendDestination & destination, + EmberApsFrame * apsFrame, uint16_t msgLen, uint8_t * message, + EmberStatus status); + +/** @brief AdministratorCommissioning Cluster Client Message Sent + * + * Client Message Sent + * + * @param type The type of message sent + * @param destination The destination to which the message was sent + * @param apsFrame The APS frame for the message + * @param msgLen The length of the message + * @param message The message that was sent + * @param status The status of the sent message + */ +void emberAfAdministratorCommissioningClusterClientMessageSentCallback(const chip::MessageSendDestination & destination, + EmberApsFrame * apsFrame, uint16_t msgLen, uint8_t * message, + EmberStatus status); + +/** @brief AdministratorCommissioning Cluster Server Pre Attribute Changed + * + * Server Pre Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute to be changed + * @param attributeType Attribute type + * @param size Attribute size + * @param value Attribute value + */ +EmberAfStatus emberAfAdministratorCommissioningClusterServerPreAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + EmberAfAttributeType attributeType, + uint16_t size, uint8_t * value); + +/** @brief AdministratorCommissioning Cluster Client Pre Attribute Changed + * + * Client Pre Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute to be changed + * @param attributeType Attribute type + * @param size Attribute size + * @param value Attribute value + */ +EmberAfStatus emberAfAdministratorCommissioningClusterClientPreAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + EmberAfAttributeType attributeType, + uint16_t size, uint8_t * value); + +/** @brief AdministratorCommissioning Cluster Server Tick + * + * Server Tick + * + * @param endpoint Endpoint that is being served + */ +void emberAfAdministratorCommissioningClusterServerTickCallback(chip::EndpointId endpoint); + +/** @brief AdministratorCommissioning Cluster Client Tick + * + * Client Tick + * + * @param endpoint Endpoint that is being served + */ +void emberAfAdministratorCommissioningClusterClientTickCallback(chip::EndpointId endpoint); + // // Operational Credentials Cluster // @@ -15796,6 +15944,23 @@ bool emberAfBridgedDeviceBasicClusterLeaveCallback(chip::EndpointId endpoint, ch * @brief Cluster ReachableChanged Command callback (from server) */ bool emberAfBridgedDeviceBasicClusterReachableChangedCallback(chip::EndpointId endpoint, chip::app::CommandSender * commandObj); +/** + * @brief Cluster OpenCommissioningWindow Command callback (from client) + */ +bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( + chip::EndpointId endpoint, chip::app::CommandHandler * commandObj, uint16_t CommissioningTimeout, chip::ByteSpan PAKEVerifier, + uint16_t Discriminator, uint32_t Iterations, chip::ByteSpan Salt, uint16_t PasscodeID); +/** + * @brief Cluster OpenBasicCommissioningWindow Command callback (from client) + */ +bool emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(chip::EndpointId endpoint, + chip::app::CommandHandler * commandObj, + uint16_t CommissioningTimeout); +/** + * @brief Cluster RevokeCommissioning Command callback (from client) + */ +bool emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(chip::EndpointId endpoint, + chip::app::CommandHandler * commandObj); /** * @brief Cluster SetFabric Command callback (from client) */ diff --git a/src/app/common/gen/client-command-macro.h b/src/app/common/gen/client-command-macro.h index fe0b41818cace1..5a3763f5f531e3 100644 --- a/src/app/common/gen/client-command-macro.h +++ b/src/app/common/gen/client-command-macro.h @@ -2211,6 +2211,42 @@ \ ZCL_REACHABLE_CHANGED_COMMAND_ID, "", ); +/** @brief Command description for OpenCommissioningWindow + * + * Command: OpenCommissioningWindow + * @param CommissioningTimeout INT16U + * @param PAKEVerifier OCTET_STRING + * @param Discriminator INT16U + * @param Iterations INT32U + * @param Salt OCTET_STRING + * @param PasscodeID INT16U + */ +#define emberAfFillCommandAdministratorCommissioningClusterOpenCommissioningWindow(CommissioningTimeout, PAKEVerifier, \ + Discriminator, Iterations, Salt, PasscodeID) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_OPEN_COMMISSIONING_WINDOW_COMMAND_ID, "uuuuuu", CommissioningTimeout, PAKEVerifier, \ + Discriminator, Iterations, Salt, PasscodeID); + +/** @brief Command description for OpenBasicCommissioningWindow + * + * Command: OpenBasicCommissioningWindow + * @param CommissioningTimeout INT16U + */ +#define emberAfFillCommandAdministratorCommissioningClusterOpenBasicCommissioningWindow(CommissioningTimeout) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_OPEN_BASIC_COMMISSIONING_WINDOW_COMMAND_ID, "u", CommissioningTimeout); + +/** @brief Command description for RevokeCommissioning + * + * Command: RevokeCommissioning + */ +#define emberAfFillCommandAdministratorCommissioningClusterRevokeCommissioning() \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_REVOKE_COMMISSIONING_COMMAND_ID, "", ); + /** @brief Command description for SetFabric * * Command: SetFabric diff --git a/src/app/common/gen/cluster-id.h b/src/app/common/gen/cluster-id.h index 6a34d97e0627b4..fef3779fe49fda 100644 --- a/src/app/common/gen/cluster-id.h +++ b/src/app/common/gen/cluster-id.h @@ -106,6 +106,9 @@ static constexpr chip::ClusterId ZCL_BRIDGED_DEVICE_BASIC_CLUSTER_ID = 0x0039; // Definitions for cluster: Switch static constexpr chip::ClusterId ZCL_SWITCH_CLUSTER_ID = 0x003B; +// Definitions for cluster: AdministratorCommissioning +static constexpr chip::ClusterId ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID = 0x003C; + // Definitions for cluster: Operational Credentials static constexpr chip::ClusterId ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID = 0x003E; diff --git a/src/app/common/gen/command-id.h b/src/app/common/gen/command-id.h index f5db578b77c44c..2649cb60b0b911 100644 --- a/src/app/common/gen/command-id.h +++ b/src/app/common/gen/command-id.h @@ -222,6 +222,11 @@ #define ZCL_LEAVE_COMMAND_ID (0x02) #define ZCL_REACHABLE_CHANGED_COMMAND_ID (0x03) +// Commands for cluster: AdministratorCommissioning +#define ZCL_OPEN_COMMISSIONING_WINDOW_COMMAND_ID (0x00) +#define ZCL_OPEN_BASIC_COMMISSIONING_WINDOW_COMMAND_ID (0x01) +#define ZCL_REVOKE_COMMISSIONING_COMMAND_ID (0x02) + // Commands for cluster: Operational Credentials #define ZCL_SET_FABRIC_COMMAND_ID (0x00) #define ZCL_SET_FABRIC_RESPONSE_COMMAND_ID (0x01) diff --git a/src/app/common/gen/enums.h b/src/app/common/gen/enums.h index f19a2b10978283..65f27f53ddc0c7 100644 --- a/src/app/common/gen/enums.h +++ b/src/app/common/gen/enums.h @@ -1377,6 +1377,14 @@ enum EmberAfStartUpOnOffValue : uint8_t EMBER_ZCL_START_UP_ON_OFF_VALUE_SET_TO_PREVIOUS = 255, }; +// Enum for StatusCode +enum EmberAfStatusCode : uint8_t +{ + EMBER_ZCL_STATUS_CODE_SUCCESS = 0, + EMBER_ZCL_STATUS_CODE_BUSY = 1, + EMBER_ZCL_STATUS_CODE_GENERAL_ERROR = 2, +}; + // Enum for StepMode enum EmberAfStepMode : uint8_t { diff --git a/src/app/common/gen/ids/Clusters.h b/src/app/common/gen/ids/Clusters.h index a44c9d1d3b0d85..77dde8cff34ebe 100644 --- a/src/app/common/gen/ids/Clusters.h +++ b/src/app/common/gen/ids/Clusters.h @@ -109,6 +109,9 @@ static constexpr ClusterId Id = 0x00000039; namespace Switch { static constexpr ClusterId Id = 0x0000003B; } // namespace Switch +namespace AdministratorCommissioning { +static constexpr ClusterId Id = 0x0000003C; +} // namespace AdministratorCommissioning namespace OperationalCredentials { static constexpr ClusterId Id = 0x0000003E; } // namespace OperationalCredentials diff --git a/src/app/common/gen/ids/Commands.h b/src/app/common/gen/ids/Commands.h index 87978ddfd102fe..dbb02dde242d87 100644 --- a/src/app/common/gen/ids/Commands.h +++ b/src/app/common/gen/ids/Commands.h @@ -332,6 +332,16 @@ static constexpr CommandId ReachableChanged = 0x00000003; } // namespace Commands } // namespace BridgedDeviceBasic +namespace AdministratorCommissioning { +namespace Commands { +namespace Ids { +static constexpr CommandId OpenCommissioningWindow = 0x00000000; +static constexpr CommandId OpenBasicCommissioningWindow = 0x00000001; +static constexpr CommandId RevokeCommissioning = 0x00000002; +} // namespace Ids +} // namespace Commands +} // namespace AdministratorCommissioning + namespace OperationalCredentials { namespace Commands { namespace Ids { diff --git a/src/app/common/gen/print-cluster.h b/src/app/common/gen/print-cluster.h index 3b0287b3a97d4d..d50842bf867ccf 100644 --- a/src/app/common/gen/print-cluster.h +++ b/src/app/common/gen/print-cluster.h @@ -195,6 +195,13 @@ #define CHIP_PRINTCLUSTER_SWITCH_CLUSTER #endif +#if defined(ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_SERVER) || defined(ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_CLIENT) +#define CHIP_PRINTCLUSTER_ADMINISTRATOR_COMMISSIONING_CLUSTER \ + { ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID, 60, "AdministratorCommissioning" }, +#else +#define CHIP_PRINTCLUSTER_ADMINISTRATOR_COMMISSIONING_CLUSTER +#endif + #if defined(ZCL_USING_OPERATIONAL_CREDENTIALS_CLUSTER_SERVER) || defined(ZCL_USING_OPERATIONAL_CREDENTIALS_CLUSTER_CLIENT) #define CHIP_PRINTCLUSTER_OPERATIONAL_CREDENTIALS_CLUSTER { ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID, 62, "Operational Credentials" }, #else @@ -747,6 +754,7 @@ CHIP_PRINTCLUSTER_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER \ CHIP_PRINTCLUSTER_BRIDGED_DEVICE_BASIC_CLUSTER \ CHIP_PRINTCLUSTER_SWITCH_CLUSTER \ + CHIP_PRINTCLUSTER_ADMINISTRATOR_COMMISSIONING_CLUSTER \ CHIP_PRINTCLUSTER_OPERATIONAL_CREDENTIALS_CLUSTER \ CHIP_PRINTCLUSTER_FIXED_LABEL_CLUSTER \ CHIP_PRINTCLUSTER_SHADE_CONFIG_CLUSTER \ diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index 332db587280cdb..251dd017faa7ae 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -3,6 +3,7 @@ "xmlRoot": [".", "./data-model/chip/", "./data-model/silabs/"], "xmlFile": [ "account-login-cluster.xml", + "administrator-commissioning-cluster.xml", "application-basic-cluster.xml", "application-launcher-cluster.xml", "audio-output-cluster.xml", diff --git a/src/app/zap_cluster_list.py b/src/app/zap_cluster_list.py index c4fd958f297f25..75f1520289e90b 100755 --- a/src/app/zap_cluster_list.py +++ b/src/app/zap_cluster_list.py @@ -12,6 +12,7 @@ 'ALARM_CLUSTER': [], 'APPLICATION_BASIC_CLUSTER': ['application-basic-server'], 'ACCOUNT_LOGIN_CLUSTER': ['account-login-server'], + 'ADMINISTRATOR_COMMISSIONING_CLUSTER': ['administrator-commissioning-server'], 'APPLICATION_LAUNCHER_CLUSTER': ['application-launcher-server'], 'AUDIO_OUTPUT_CLUSTER': ['audio-output-server'], 'BARRIER_CONTROL_CLUSTER': ['barrier-control-server'], @@ -71,6 +72,7 @@ CLIENT_CLUSTERS: typing.Dict[str, typing.List[str]] = { 'ALARM_CLUSTER': [], 'ACCOUNT_LOGIN_CLUSTER': [], + 'ADMINISTRATOR_COMMISSIONING_CLUSTER': [], 'APPLICATION_LAUNCHER_CLUSTER': [], 'AUDIO_OUTPUT_CLUSTER': [], 'APPLICATION_BASIC_CLUSTER': [], diff --git a/src/controller/data_model/controller-clusters.zap b/src/controller/data_model/controller-clusters.zap index 39257ed97318c8..0aac38125ec855 100644 --- a/src/controller/data_model/controller-clusters.zap +++ b/src/controller/data_model/controller-clusters.zap @@ -3617,6 +3617,83 @@ } ] }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + } + ], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "client", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "AdministratorCommissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [], + "attributes": [ + { + "name": "cluster revision", + "code": 65533, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 0, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "Operational Credentials", "code": 62, diff --git a/src/controller/data_model/gen/CHIPClusters.cpp b/src/controller/data_model/gen/CHIPClusters.cpp index 3f535f039c426f..7346f1289cb5c9 100644 --- a/src/controller/data_model/gen/CHIPClusters.cpp +++ b/src/controller/data_model/gen/CHIPClusters.cpp @@ -187,6 +187,166 @@ CHIP_ERROR AccountLoginCluster::ReadAttributeClusterRevision(Callback::Cancelabl BasicAttributeFilter); } +// AdministratorCommissioning Cluster Commands +CHIP_ERROR AdministratorCommissioningCluster::OpenBasicCommissioningWindow(Callback::Cancelable * onSuccessCallback, + Callback::Cancelable * onFailureCallback, + uint16_t commissioningTimeout) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + app::CommandSender * sender = nullptr; + TLV::TLVWriter * writer = nullptr; + uint8_t argSeqNumber = 0; + + // Used when encoding non-empty command. Suppress error message when encoding empty commands. + (void) writer; + (void) argSeqNumber; + + VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); + + app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, + AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + SuccessOrExit(err = chip::app::InteractionModelEngine::GetInstance()->NewCommandSender(&sender)); + + SuccessOrExit(err = sender->PrepareCommand(cmdParams)); + + VerifyOrExit((writer = sender->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + // commissioningTimeout: int16u + SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), commissioningTimeout)); + + SuccessOrExit(err = sender->FinishCommand()); + + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(sender, onSuccessCallback, onFailureCallback); + + err = mDevice->SendCommands(sender); + +exit: + // On error, we are responsible to close the sender. + if (err != CHIP_NO_ERROR && sender != nullptr) + { + sender->Shutdown(); + } + return err; +} + +CHIP_ERROR AdministratorCommissioningCluster::OpenCommissioningWindow(Callback::Cancelable * onSuccessCallback, + Callback::Cancelable * onFailureCallback, + uint16_t commissioningTimeout, chip::ByteSpan pAKEVerifier, + uint16_t discriminator, uint32_t iterations, + chip::ByteSpan salt, uint16_t passcodeID) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + app::CommandSender * sender = nullptr; + TLV::TLVWriter * writer = nullptr; + uint8_t argSeqNumber = 0; + + // Used when encoding non-empty command. Suppress error message when encoding empty commands. + (void) writer; + (void) argSeqNumber; + + VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); + + app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, + AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + SuccessOrExit(err = chip::app::InteractionModelEngine::GetInstance()->NewCommandSender(&sender)); + + SuccessOrExit(err = sender->PrepareCommand(cmdParams)); + + VerifyOrExit((writer = sender->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + // commissioningTimeout: int16u + SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), commissioningTimeout)); + // pAKEVerifier: octetString + SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), pAKEVerifier)); + // discriminator: int16u + SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), discriminator)); + // iterations: int32u + SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), iterations)); + // salt: octetString + SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), salt)); + // passcodeID: int16u + SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), passcodeID)); + + SuccessOrExit(err = sender->FinishCommand()); + + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(sender, onSuccessCallback, onFailureCallback); + + err = mDevice->SendCommands(sender); + +exit: + // On error, we are responsible to close the sender. + if (err != CHIP_NO_ERROR && sender != nullptr) + { + sender->Shutdown(); + } + return err; +} + +CHIP_ERROR AdministratorCommissioningCluster::RevokeCommissioning(Callback::Cancelable * onSuccessCallback, + Callback::Cancelable * onFailureCallback) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + app::CommandSender * sender = nullptr; + TLV::TLVWriter * writer = nullptr; + uint8_t argSeqNumber = 0; + + // Used when encoding non-empty command. Suppress error message when encoding empty commands. + (void) writer; + (void) argSeqNumber; + + VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); + + app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, + AdministratorCommissioning::Commands::Ids::RevokeCommissioning, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + SuccessOrExit(err = chip::app::InteractionModelEngine::GetInstance()->NewCommandSender(&sender)); + + SuccessOrExit(err = sender->PrepareCommand(cmdParams)); + + // Command takes no arguments. + + SuccessOrExit(err = sender->FinishCommand()); + + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(sender, onSuccessCallback, onFailureCallback); + + err = mDevice->SendCommands(sender); + +exit: + // On error, we are responsible to close the sender. + if (err != CHIP_NO_ERROR && sender != nullptr) + { + sender->Shutdown(); + } + return err; +} + +// AdministratorCommissioning Cluster Attributes +CHIP_ERROR AdministratorCommissioningCluster::DiscoverAttributes(Callback::Cancelable * onSuccessCallback, + Callback::Cancelable * onFailureCallback) +{ + COMMAND_HEADER("DiscoverAdministratorCommissioningAttributes", AdministratorCommissioning::Id); + buf.Put8(kFrameControlGlobalCommand).Put8(seqNum).Put32(Globals::Commands::Ids::DiscoverAttributes).Put32(0x0000).Put8(0xFF); + COMMAND_FOOTER(); +} + +CHIP_ERROR AdministratorCommissioningCluster::ReadAttributeClusterRevision(Callback::Cancelable * onSuccessCallback, + Callback::Cancelable * onFailureCallback) +{ + chip::app::AttributePathParams attributePath; + attributePath.mEndpointId = mEndpoint; + attributePath.mClusterId = mClusterId; + attributePath.mFieldId = 0x0000FFFD; + attributePath.mFlags.Set(chip::app::AttributePathParams::Flags::kFieldIdValid); + return mDevice->SendReadAttributeRequest(attributePath, onSuccessCallback, onFailureCallback, + BasicAttributeFilter); +} + // ApplicationBasic Cluster Commands CHIP_ERROR ApplicationBasicCluster::ChangeStatus(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, uint8_t status) diff --git a/src/controller/data_model/gen/CHIPClusters.h b/src/controller/data_model/gen/CHIPClusters.h index a3f043e5349875..47ee4aec35950a 100644 --- a/src/controller/data_model/gen/CHIPClusters.h +++ b/src/controller/data_model/gen/CHIPClusters.h @@ -49,6 +49,27 @@ class DLL_EXPORT AccountLoginCluster : public ClusterBase private: }; +class DLL_EXPORT AdministratorCommissioningCluster : public ClusterBase +{ +public: + AdministratorCommissioningCluster() : ClusterBase(app::Clusters::AdministratorCommissioning::Id) {} + ~AdministratorCommissioningCluster() {} + + // Cluster Commands + CHIP_ERROR OpenBasicCommissioningWindow(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, + uint16_t commissioningTimeout); + CHIP_ERROR OpenCommissioningWindow(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, + uint16_t commissioningTimeout, chip::ByteSpan pAKEVerifier, uint16_t discriminator, + uint32_t iterations, chip::ByteSpan salt, uint16_t passcodeID); + CHIP_ERROR RevokeCommissioning(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback); + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback); + CHIP_ERROR ReadAttributeClusterRevision(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback); + +private: +}; + class DLL_EXPORT ApplicationBasicCluster : public ClusterBase { public: diff --git a/src/controller/data_model/gen/callback-stub.cpp b/src/controller/data_model/gen/callback-stub.cpp index dff0b792b78ab6..49b14f097b0e37 100644 --- a/src/controller/data_model/gen/callback-stub.cpp +++ b/src/controller/data_model/gen/callback-stub.cpp @@ -31,6 +31,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_ACCOUNT_LOGIN_CLUSTER_ID: emberAfAccountLoginClusterInitCallback(endpoint); break; + case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID: + emberAfAdministratorCommissioningClusterInitCallback(endpoint); + break; case ZCL_APPLICATION_BASIC_CLUSTER_ID: emberAfApplicationBasicClusterInitCallback(endpoint); break; @@ -183,6 +186,11 @@ void __attribute__((weak)) emberAfAccountLoginClusterInitCallback(EndpointId end // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfApplicationBasicClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/src/controller/data_model/gen/endpoint_config.h b/src/controller/data_model/gen/endpoint_config.h index fb50f48ad76c7a..5a11872202d6ce 100644 --- a/src/controller/data_model/gen/endpoint_config.h +++ b/src/controller/data_model/gen/endpoint_config.h @@ -63,7 +63,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 47 +#define GENERATED_ATTRIBUTE_COUNT 48 #define GENERATED_ATTRIBUTES \ { \ \ @@ -121,6 +121,9 @@ ZAP_SIMPLE_DEFAULT(1) }, /* cluster revision */ \ \ /* Endpoint: 1, Cluster: Switch (client) */ \ + { 0xFFFD, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(CLIENT), ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ + \ + /* Endpoint: 1, Cluster: AdministratorCommissioning (client) */ \ { 0xFFFD, ZAP_TYPE(INT16U), 2, ZAP_ATTRIBUTE_MASK(CLIENT), ZAP_SIMPLE_DEFAULT(0x0001) }, /* cluster revision */ \ \ /* Endpoint: 1, Cluster: Operational Credentials (client) */ \ @@ -218,7 +221,7 @@ #define GENERATED_FUNCTION_ARRAYS #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 48 +#define GENERATED_CLUSTER_COUNT 49 #define GENERATED_CLUSTERS \ { \ { 0x0003, ZAP_ATTRIBUTE_INDEX(0), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL }, /* Endpoint: 1, Cluster: Identify (client) */ \ @@ -267,91 +270,94 @@ }, /* Endpoint: 1, Cluster: Bridged Device Basic (client) */ \ { 0x003B, ZAP_ATTRIBUTE_INDEX(17), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL }, /* Endpoint: 1, Cluster: Switch (client) */ \ { \ - 0x003E, ZAP_ATTRIBUTE_INDEX(18), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x003C, ZAP_ATTRIBUTE_INDEX(18), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + }, /* Endpoint: 1, Cluster: AdministratorCommissioning (client) */ \ + { \ + 0x003E, ZAP_ATTRIBUTE_INDEX(19), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Operational Credentials (client) */ \ { \ - 0x0040, ZAP_ATTRIBUTE_INDEX(19), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0040, ZAP_ATTRIBUTE_INDEX(20), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Fixed Label (client) */ \ { \ - 0x0101, ZAP_ATTRIBUTE_INDEX(20), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0101, ZAP_ATTRIBUTE_INDEX(21), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Door Lock (client) */ \ { \ - 0x0102, ZAP_ATTRIBUTE_INDEX(21), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0102, ZAP_ATTRIBUTE_INDEX(22), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Window Covering (client) */ \ { \ - 0x0103, ZAP_ATTRIBUTE_INDEX(22), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0103, ZAP_ATTRIBUTE_INDEX(23), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Barrier Control (client) */ \ { \ - 0x0200, ZAP_ATTRIBUTE_INDEX(23), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0200, ZAP_ATTRIBUTE_INDEX(24), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Pump Configuration and Control (client) */ \ { \ - 0x0201, ZAP_ATTRIBUTE_INDEX(24), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0201, ZAP_ATTRIBUTE_INDEX(25), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Thermostat (client) */ \ { \ - 0x0300, ZAP_ATTRIBUTE_INDEX(25), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0300, ZAP_ATTRIBUTE_INDEX(26), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Color Control (client) */ \ { \ - 0x0402, ZAP_ATTRIBUTE_INDEX(26), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0402, ZAP_ATTRIBUTE_INDEX(27), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Temperature Measurement (client) */ \ { \ - 0x0403, ZAP_ATTRIBUTE_INDEX(27), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0403, ZAP_ATTRIBUTE_INDEX(28), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Pressure Measurement (client) */ \ { \ - 0x0404, ZAP_ATTRIBUTE_INDEX(28), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0404, ZAP_ATTRIBUTE_INDEX(29), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Flow Measurement (client) */ \ { \ - 0x0405, ZAP_ATTRIBUTE_INDEX(29), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0405, ZAP_ATTRIBUTE_INDEX(30), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Relative Humidity Measurement (client) */ \ { \ - 0x0406, ZAP_ATTRIBUTE_INDEX(30), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0406, ZAP_ATTRIBUTE_INDEX(31), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Occupancy Sensing (client) */ \ { \ - 0x0503, ZAP_ATTRIBUTE_INDEX(31), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0503, ZAP_ATTRIBUTE_INDEX(32), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Wake on LAN (client) */ \ { \ - 0x0504, ZAP_ATTRIBUTE_INDEX(32), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0504, ZAP_ATTRIBUTE_INDEX(33), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: TV Channel (client) */ \ { \ - 0x0505, ZAP_ATTRIBUTE_INDEX(33), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0505, ZAP_ATTRIBUTE_INDEX(34), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Target Navigator (client) */ \ { \ - 0x0506, ZAP_ATTRIBUTE_INDEX(34), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0506, ZAP_ATTRIBUTE_INDEX(35), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Media Playback (client) */ \ { \ - 0x0507, ZAP_ATTRIBUTE_INDEX(35), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0507, ZAP_ATTRIBUTE_INDEX(36), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Media Input (client) */ \ { \ - 0x0508, ZAP_ATTRIBUTE_INDEX(36), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0508, ZAP_ATTRIBUTE_INDEX(37), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Low Power (client) */ \ { \ - 0x0509, ZAP_ATTRIBUTE_INDEX(37), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0509, ZAP_ATTRIBUTE_INDEX(38), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Keypad Input (client) */ \ { \ - 0x050A, ZAP_ATTRIBUTE_INDEX(38), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x050A, ZAP_ATTRIBUTE_INDEX(39), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Content Launcher (client) */ \ { \ - 0x050B, ZAP_ATTRIBUTE_INDEX(39), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x050B, ZAP_ATTRIBUTE_INDEX(40), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Audio Output (client) */ \ { \ - 0x050C, ZAP_ATTRIBUTE_INDEX(40), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x050C, ZAP_ATTRIBUTE_INDEX(41), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Application Launcher (client) */ \ { \ - 0x050D, ZAP_ATTRIBUTE_INDEX(41), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x050D, ZAP_ATTRIBUTE_INDEX(42), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Application Basic (client) */ \ { \ - 0x050E, ZAP_ATTRIBUTE_INDEX(42), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x050E, ZAP_ATTRIBUTE_INDEX(43), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Account Login (client) */ \ { \ - 0x050F, ZAP_ATTRIBUTE_INDEX(43), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x050F, ZAP_ATTRIBUTE_INDEX(44), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Test Cluster (client) */ \ { \ - 0x0B04, ZAP_ATTRIBUTE_INDEX(44), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x0B04, ZAP_ATTRIBUTE_INDEX(45), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Electrical Measurement (client) */ \ { \ - 0xF000, ZAP_ATTRIBUTE_INDEX(45), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0xF000, ZAP_ATTRIBUTE_INDEX(46), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Binding (client) */ \ { \ - 0xF004, ZAP_ATTRIBUTE_INDEX(46), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0xF004, ZAP_ATTRIBUTE_INDEX(47), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Group Key Management (client) */ \ } @@ -360,7 +366,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 48, 94 }, \ + { ZAP_CLUSTER_INDEX(0), 49, 96 }, \ } // Largest attribute size is needed for various buffers @@ -370,7 +376,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (4) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (94) +#define ATTRIBUTE_MAX_SIZE (96) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (1) @@ -414,7 +420,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (231) +#define EMBER_AF_GENERATED_COMMAND_COUNT (234) #define GENERATED_COMMANDS \ { \ \ @@ -530,6 +536,11 @@ { 0x0039, 0x02, 0 }, /* Leave */ \ { 0x0039, 0x03, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* ReachableChanged */ \ \ + /* Endpoint: 1, Cluster: AdministratorCommissioning (client) */ \ + { 0x003C, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenCommissioningWindow */ \ + { 0x003C, 0x01, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* OpenBasicCommissioningWindow */ \ + { 0x003C, 0x02, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RevokeCommissioning */ \ + \ /* Endpoint: 1, Cluster: Operational Credentials (client) */ \ { 0x003E, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* SetFabric */ \ { 0x003E, 0x01, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* SetFabricResponse */ \ diff --git a/src/controller/data_model/gen/gen_config.h b/src/controller/data_model/gen/gen_config.h index 07d1b5c5bc2969..c832c2f43dadf3 100644 --- a/src/controller/data_model/gen/gen_config.h +++ b/src/controller/data_model/gen/gen_config.h @@ -30,6 +30,7 @@ /**** Cluster endpoint counts ****/ #define EMBER_AF_ACCOUNT_LOGIN_CLUSTER_CLIENT_ENDPOINT_COUNT (1) +#define EMBER_AF_ADMINISTRATOR_COMMISSIONING_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_APPLICATION_BASIC_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_APPLICATION_LAUNCHER_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_AUDIO_OUTPUT_CLUSTER_CLIENT_ENDPOINT_COUNT (1) @@ -84,6 +85,10 @@ #define ZCL_USING_ACCOUNT_LOGIN_CLUSTER_CLIENT #define EMBER_AF_PLUGIN_ACCOUNT_LOGIN_CLIENT +// Use this macro to check if the client side of the AdministratorCommissioning cluster is included +#define ZCL_USING_ADMINISTRATOR_COMMISSIONING_CLUSTER_CLIENT +#define EMBER_AF_PLUGIN_ADMINISTRATOR_COMMISSIONING_CLIENT + // Use this macro to check if the client side of the Application Basic cluster is included #define ZCL_USING_APPLICATION_BASIC_CLUSTER_CLIENT #define EMBER_AF_PLUGIN_APPLICATION_BASIC_CLIENT diff --git a/src/controller/java/gen/CHIPClusters-JNI.cpp b/src/controller/java/gen/CHIPClusters-JNI.cpp index e0063c1ceb20e6..a1c56971ddec0b 100644 --- a/src/controller/java/gen/CHIPClusters-JNI.cpp +++ b/src/controller/java/gen/CHIPClusters-JNI.cpp @@ -7883,6 +7883,197 @@ JNI_METHOD(void, AccountLoginCluster, readClusterRevisionAttribute)(JNIEnv * env ReturnIllegalStateException(env, callback, "Error reading attribute", err); } } +JNI_METHOD(jlong, AdministratorCommissioningCluster, initWithDevice)(JNIEnv * env, jobject self, jlong devicePtr, jint endpointId) +{ + StackLockGuard lock(JniReferences::GetInstance().GetStackLock()); + AdministratorCommissioningCluster * cppCluster = new AdministratorCommissioningCluster(); + + cppCluster->Associate(reinterpret_cast(devicePtr), endpointId); + return reinterpret_cast(cppCluster); +} + +JNI_METHOD(void, AdministratorCommissioningCluster, openBasicCommissioningWindow) +(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint commissioningTimeout) +{ + StackLockGuard lock(JniReferences::GetInstance().GetStackLock()); + CHIP_ERROR err = CHIP_NO_ERROR; + AdministratorCommissioningCluster * cppCluster; + + CHIPDefaultSuccessCallback * onSuccess; + CHIPDefaultFailureCallback * onFailure; + + cppCluster = reinterpret_cast(clusterPtr); + VerifyOrExit(cppCluster != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + onSuccess = new CHIPDefaultSuccessCallback(callback); + VerifyOrExit(onSuccess != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + onFailure = new CHIPDefaultFailureCallback(callback); + VerifyOrExit(onFailure != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + err = cppCluster->OpenBasicCommissioningWindow(onSuccess->Cancel(), onFailure->Cancel(), commissioningTimeout); + SuccessOrExit(err); + +exit: + if (err != CHIP_NO_ERROR) + { + delete onSuccess; + delete onFailure; + + jthrowable exception; + jmethodID method; + + err = JniReferences::GetInstance().FindMethod(env, callback, "onError", "(Ljava/lang/Exception;)V", &method); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Error throwing IllegalStateException %" CHIP_ERROR_FORMAT, ChipError::FormatError(err)); + return; + } + + err = CreateIllegalStateException(env, "Error invoking cluster", ChipError::FormatError(err), exception); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Error throwing IllegalStateException %" CHIP_ERROR_FORMAT, ChipError::FormatError(err)); + return; + } + env->CallVoidMethod(callback, method, exception); + } +} +JNI_METHOD(void, AdministratorCommissioningCluster, openCommissioningWindow) +(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint commissioningTimeout, jbyteArray pAKEVerifier, + jint discriminator, jlong iterations, jbyteArray salt, jint passcodeID) +{ + StackLockGuard lock(JniReferences::GetInstance().GetStackLock()); + CHIP_ERROR err = CHIP_NO_ERROR; + AdministratorCommissioningCluster * cppCluster; + + JniByteArray pAKEVerifierArr(env, pAKEVerifier); + JniByteArray saltArr(env, salt); + CHIPDefaultSuccessCallback * onSuccess; + CHIPDefaultFailureCallback * onFailure; + + cppCluster = reinterpret_cast(clusterPtr); + VerifyOrExit(cppCluster != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + onSuccess = new CHIPDefaultSuccessCallback(callback); + VerifyOrExit(onSuccess != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + onFailure = new CHIPDefaultFailureCallback(callback); + VerifyOrExit(onFailure != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + err = cppCluster->OpenCommissioningWindow(onSuccess->Cancel(), onFailure->Cancel(), commissioningTimeout, + chip::ByteSpan((const uint8_t *) pAKEVerifierArr.data(), pAKEVerifierArr.size()), + discriminator, iterations, + chip::ByteSpan((const uint8_t *) saltArr.data(), saltArr.size()), passcodeID); + SuccessOrExit(err); + +exit: + if (err != CHIP_NO_ERROR) + { + delete onSuccess; + delete onFailure; + + jthrowable exception; + jmethodID method; + + err = JniReferences::GetInstance().FindMethod(env, callback, "onError", "(Ljava/lang/Exception;)V", &method); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Error throwing IllegalStateException %" CHIP_ERROR_FORMAT, ChipError::FormatError(err)); + return; + } + + err = CreateIllegalStateException(env, "Error invoking cluster", ChipError::FormatError(err), exception); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Error throwing IllegalStateException %" CHIP_ERROR_FORMAT, ChipError::FormatError(err)); + return; + } + env->CallVoidMethod(callback, method, exception); + } +} +JNI_METHOD(void, AdministratorCommissioningCluster, revokeCommissioning) +(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback) +{ + StackLockGuard lock(JniReferences::GetInstance().GetStackLock()); + CHIP_ERROR err = CHIP_NO_ERROR; + AdministratorCommissioningCluster * cppCluster; + + CHIPDefaultSuccessCallback * onSuccess; + CHIPDefaultFailureCallback * onFailure; + + cppCluster = reinterpret_cast(clusterPtr); + VerifyOrExit(cppCluster != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + onSuccess = new CHIPDefaultSuccessCallback(callback); + VerifyOrExit(onSuccess != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + onFailure = new CHIPDefaultFailureCallback(callback); + VerifyOrExit(onFailure != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + err = cppCluster->RevokeCommissioning(onSuccess->Cancel(), onFailure->Cancel()); + SuccessOrExit(err); + +exit: + if (err != CHIP_NO_ERROR) + { + delete onSuccess; + delete onFailure; + + jthrowable exception; + jmethodID method; + + err = JniReferences::GetInstance().FindMethod(env, callback, "onError", "(Ljava/lang/Exception;)V", &method); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Error throwing IllegalStateException %" CHIP_ERROR_FORMAT, ChipError::FormatError(err)); + return; + } + + err = CreateIllegalStateException(env, "Error invoking cluster", ChipError::FormatError(err), exception); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Error throwing IllegalStateException %" CHIP_ERROR_FORMAT, ChipError::FormatError(err)); + return; + } + env->CallVoidMethod(callback, method, exception); + } +} + +JNI_METHOD(void, AdministratorCommissioningCluster, readClusterRevisionAttribute) +(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback) +{ + StackLockGuard lock(JniReferences::GetInstance().GetStackLock()); + CHIPInt16uAttributeCallback * onSuccess = new CHIPInt16uAttributeCallback(callback); + if (!onSuccess) + { + ReturnIllegalStateException(env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY); + return; + } + + CHIPDefaultFailureCallback * onFailure = new CHIPDefaultFailureCallback(callback); + if (!onFailure) + { + delete onSuccess; + ReturnIllegalStateException(env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY); + return; + } + + CHIP_ERROR err = CHIP_NO_ERROR; + AdministratorCommissioningCluster * cppCluster = reinterpret_cast(clusterPtr); + if (cppCluster == nullptr) + { + delete onSuccess; + delete onFailure; + ReturnIllegalStateException(env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE); + return; + } + + err = cppCluster->ReadAttributeClusterRevision(onSuccess->Cancel(), onFailure->Cancel()); + if (err != CHIP_NO_ERROR) + { + delete onSuccess; + delete onFailure; + ReturnIllegalStateException(env, callback, "Error reading attribute", err); + } +} JNI_METHOD(jlong, ApplicationBasicCluster, initWithDevice)(JNIEnv * env, jobject self, jlong devicePtr, jint endpointId) { StackLockGuard lock(JniReferences::GetInstance().GetStackLock()); diff --git a/src/controller/java/gen/ChipClusters.java b/src/controller/java/gen/ChipClusters.java index f82e78d929018c..990c49e40f62a0 100644 --- a/src/controller/java/gen/ChipClusters.java +++ b/src/controller/java/gen/ChipClusters.java @@ -123,6 +123,65 @@ private native void readClusterRevisionAttribute( long chipClusterPtr, IntegerAttributeCallback callback); } + public static class AdministratorCommissioningCluster extends BaseChipCluster { + public AdministratorCommissioningCluster(long devicePtr, int endpointId) { + super(devicePtr, endpointId); + } + + @Override + public native long initWithDevice(long devicePtr, int endpointId); + + public void openBasicCommissioningWindow( + DefaultClusterCallback callback, int commissioningTimeout) { + openBasicCommissioningWindow(chipClusterPtr, callback, commissioningTimeout); + } + + public void openCommissioningWindow( + DefaultClusterCallback callback, + int commissioningTimeout, + byte[] pAKEVerifier, + int discriminator, + long iterations, + byte[] salt, + int passcodeID) { + openCommissioningWindow( + chipClusterPtr, + callback, + commissioningTimeout, + pAKEVerifier, + discriminator, + iterations, + salt, + passcodeID); + } + + public void revokeCommissioning(DefaultClusterCallback callback) { + revokeCommissioning(chipClusterPtr, callback); + } + + private native void openBasicCommissioningWindow( + long chipClusterPtr, DefaultClusterCallback callback, int commissioningTimeout); + + private native void openCommissioningWindow( + long chipClusterPtr, + DefaultClusterCallback callback, + int commissioningTimeout, + byte[] pAKEVerifier, + int discriminator, + long iterations, + byte[] salt, + int passcodeID); + + private native void revokeCommissioning(long chipClusterPtr, DefaultClusterCallback callback); + + public void readClusterRevisionAttribute(IntegerAttributeCallback callback) { + readClusterRevisionAttribute(chipClusterPtr, callback); + } + + private native void readClusterRevisionAttribute( + long chipClusterPtr, IntegerAttributeCallback callback); + } + public static class ApplicationBasicCluster extends BaseChipCluster { public ApplicationBasicCluster(long devicePtr, int endpointId) { super(devicePtr, endpointId); diff --git a/src/controller/python/chip/clusters/CHIPClusters.cpp b/src/controller/python/chip/clusters/CHIPClusters.cpp index 9b61f4762f6855..ac992a3649d1ba 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.cpp +++ b/src/controller/python/chip/clusters/CHIPClusters.cpp @@ -373,6 +373,50 @@ chip::ChipError::StorageType chip_ime_ReadAttribute_AccountLogin_ClusterRevision } // End of Cluster AccountLogin +// Cluster AdministratorCommissioning + +chip::ChipError::StorageType chip_ime_AppendCommand_AdministratorCommissioning_OpenBasicCommissioningWindow( + chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t commissioningTimeout) +{ + VerifyOrReturnError(device != nullptr, chip::ChipError::AsInteger(CHIP_ERROR_INVALID_ARGUMENT)); + chip::Controller::AdministratorCommissioningCluster cluster; + cluster.Associate(device, ZCLendpointId); + return chip::ChipError::AsInteger(cluster.OpenBasicCommissioningWindow(nullptr, nullptr, commissioningTimeout)); +} +chip::ChipError::StorageType chip_ime_AppendCommand_AdministratorCommissioning_OpenCommissioningWindow( + chip::Controller::Device * device, chip::EndpointId ZCLendpointId, chip::GroupId, uint16_t commissioningTimeout, + const uint8_t * pAKEVerifier, uint32_t pAKEVerifier_Len, uint16_t discriminator, uint32_t iterations, const uint8_t * salt, + uint32_t salt_Len, uint16_t passcodeID) +{ + VerifyOrReturnError(device != nullptr, chip::ChipError::AsInteger(CHIP_ERROR_INVALID_ARGUMENT)); + chip::Controller::AdministratorCommissioningCluster cluster; + cluster.Associate(device, ZCLendpointId); + return chip::ChipError::AsInteger(cluster.OpenCommissioningWindow(nullptr, nullptr, commissioningTimeout, + chip::ByteSpan(pAKEVerifier, pAKEVerifier_Len), discriminator, + iterations, chip::ByteSpan(salt, salt_Len), passcodeID)); +} +chip::ChipError::StorageType +chip_ime_AppendCommand_AdministratorCommissioning_RevokeCommissioning(chip::Controller::Device * device, + chip::EndpointId ZCLendpointId, chip::GroupId) +{ + VerifyOrReturnError(device != nullptr, chip::ChipError::AsInteger(CHIP_ERROR_INVALID_ARGUMENT)); + chip::Controller::AdministratorCommissioningCluster cluster; + cluster.Associate(device, ZCLendpointId); + return chip::ChipError::AsInteger(cluster.RevokeCommissioning(nullptr, nullptr)); +} + +chip::ChipError::StorageType chip_ime_ReadAttribute_AdministratorCommissioning_ClusterRevision(chip::Controller::Device * device, + chip::EndpointId ZCLendpointId, + chip::GroupId /* ZCLgroupId */) +{ + VerifyOrReturnError(device != nullptr, chip::ChipError::AsInteger(CHIP_ERROR_INVALID_ARGUMENT)); + chip::Controller::AdministratorCommissioningCluster cluster; + cluster.Associate(device, ZCLendpointId); + return chip::ChipError::AsInteger( + cluster.ReadAttributeClusterRevision(gInt16uAttributeCallback.Cancel(), gDefaultFailureCallback.Cancel())); +} + +// End of Cluster AdministratorCommissioning // Cluster ApplicationBasic chip::ChipError::StorageType chip_ime_AppendCommand_ApplicationBasic_ChangeStatus(chip::Controller::Device * device, diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py index b49fe26260f2a0..805412a569876f 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.py +++ b/src/controller/python/chip/clusters/CHIPClusters.py @@ -47,6 +47,21 @@ def ListClusterCommands(self): "setupPIN": "str", }, }, + "AdministratorCommissioning": { + "OpenBasicCommissioningWindow": { + "commissioningTimeout": "int", + }, + "OpenCommissioningWindow": { + "commissioningTimeout": "int", + "pAKEVerifier": "bytes", + "discriminator": "int", + "iterations": "int", + "salt": "bytes", + "passcodeID": "int", + }, + "RevokeCommissioning": { + }, + }, "ApplicationBasic": { "ChangeStatus": { "status": "int", @@ -748,6 +763,12 @@ def ListClusterAttributes(self): "type": "int", }, }, + "AdministratorCommissioning": { + "ClusterRevision": { + "attributeId": 0xFFFD, + "type": "int", + }, + }, "ApplicationBasic": { "VendorName": { "attributeId": 0x0000, @@ -2336,6 +2357,18 @@ def ClusterAccountLogin_CommandLogin(self, device: ctypes.c_void_p, ZCLendpoint: return self._chipLib.chip_ime_AppendCommand_AccountLogin_Login( device, ZCLendpoint, ZCLgroupid, tempAccountIdentifier, len(tempAccountIdentifier), setupPIN, len(setupPIN) ) + def ClusterAdministratorCommissioning_CommandOpenBasicCommissioningWindow(self, device: ctypes.c_void_p, ZCLendpoint: int, ZCLgroupid: int, commissioningTimeout: int): + return self._chipLib.chip_ime_AppendCommand_AdministratorCommissioning_OpenBasicCommissioningWindow( + device, ZCLendpoint, ZCLgroupid, commissioningTimeout + ) + def ClusterAdministratorCommissioning_CommandOpenCommissioningWindow(self, device: ctypes.c_void_p, ZCLendpoint: int, ZCLgroupid: int, commissioningTimeout: int, pAKEVerifier: bytes, discriminator: int, iterations: int, salt: bytes, passcodeID: int): + return self._chipLib.chip_ime_AppendCommand_AdministratorCommissioning_OpenCommissioningWindow( + device, ZCLendpoint, ZCLgroupid, commissioningTimeout, pAKEVerifier, len(pAKEVerifier), discriminator, iterations, salt, len(salt), passcodeID + ) + def ClusterAdministratorCommissioning_CommandRevokeCommissioning(self, device: ctypes.c_void_p, ZCLendpoint: int, ZCLgroupid: int): + return self._chipLib.chip_ime_AppendCommand_AdministratorCommissioning_RevokeCommissioning( + device, ZCLendpoint, ZCLgroupid + ) def ClusterApplicationBasic_CommandChangeStatus(self, device: ctypes.c_void_p, ZCLendpoint: int, ZCLgroupid: int, status: int): return self._chipLib.chip_ime_AppendCommand_ApplicationBasic_ChangeStatus( device, ZCLendpoint, ZCLgroupid, status @@ -2953,6 +2986,8 @@ def ClusterWindowCovering_CommandUpOrOpen(self, device: ctypes.c_void_p, ZCLendp def ClusterAccountLogin_ReadAttributeClusterRevision(self, device: ctypes.c_void_p, ZCLendpoint: int, ZCLgroupid: int): return self._chipLib.chip_ime_ReadAttribute_AccountLogin_ClusterRevision(device, ZCLendpoint, ZCLgroupid) + def ClusterAdministratorCommissioning_ReadAttributeClusterRevision(self, device: ctypes.c_void_p, ZCLendpoint: int, ZCLgroupid: int): + return self._chipLib.chip_ime_ReadAttribute_AdministratorCommissioning_ClusterRevision(device, ZCLendpoint, ZCLgroupid) def ClusterApplicationBasic_ReadAttributeVendorName(self, device: ctypes.c_void_p, ZCLendpoint: int, ZCLgroupid: int): return self._chipLib.chip_ime_ReadAttribute_ApplicationBasic_VendorName(device, ZCLendpoint, ZCLgroupid) def ClusterApplicationBasic_ReadAttributeVendorId(self, device: ctypes.c_void_p, ZCLendpoint: int, ZCLgroupid: int): @@ -3814,6 +3849,19 @@ def InitLib(self, chipLib): # Cluster AccountLogin ReadAttribute ClusterRevision self._chipLib.chip_ime_ReadAttribute_AccountLogin_ClusterRevision.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint16] self._chipLib.chip_ime_ReadAttribute_AccountLogin_ClusterRevision.restype = ctypes.c_uint32 + # Cluster AdministratorCommissioning + # Cluster AdministratorCommissioning Command OpenBasicCommissioningWindow + self._chipLib.chip_ime_AppendCommand_AdministratorCommissioning_OpenBasicCommissioningWindow.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint16, ctypes.c_uint16] + self._chipLib.chip_ime_AppendCommand_AdministratorCommissioning_OpenBasicCommissioningWindow.restype = ctypes.c_uint32 + # Cluster AdministratorCommissioning Command OpenCommissioningWindow + self._chipLib.chip_ime_AppendCommand_AdministratorCommissioning_OpenCommissioningWindow.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint16, ctypes.c_uint16, ctypes.c_char_p, ctypes.c_uint32, ctypes.c_uint16, ctypes.c_uint32, ctypes.c_char_p, ctypes.c_uint32, ctypes.c_uint16] + self._chipLib.chip_ime_AppendCommand_AdministratorCommissioning_OpenCommissioningWindow.restype = ctypes.c_uint32 + # Cluster AdministratorCommissioning Command RevokeCommissioning + self._chipLib.chip_ime_AppendCommand_AdministratorCommissioning_RevokeCommissioning.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint16] + self._chipLib.chip_ime_AppendCommand_AdministratorCommissioning_RevokeCommissioning.restype = ctypes.c_uint32 + # Cluster AdministratorCommissioning ReadAttribute ClusterRevision + self._chipLib.chip_ime_ReadAttribute_AdministratorCommissioning_ClusterRevision.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint16] + self._chipLib.chip_ime_ReadAttribute_AdministratorCommissioning_ClusterRevision.restype = ctypes.c_uint32 # Cluster ApplicationBasic # Cluster ApplicationBasic Command ChangeStatus self._chipLib.chip_ime_AppendCommand_ApplicationBasic_ChangeStatus.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint16, ctypes.c_uint8] diff --git a/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.h b/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.h index 4308b655701fa5..36df042b828050 100644 --- a/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.h +++ b/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.h @@ -55,6 +55,26 @@ NS_ASSUME_NONNULL_BEGIN @end +/** + * Cluster AdministratorCommissioning + * + */ +@interface CHIPAdministratorCommissioning : CHIPCluster + +- (void)openBasicCommissioningWindow:(uint16_t)commissioningTimeout responseHandler:(ResponseHandler)responseHandler; +- (void)openCommissioningWindow:(uint16_t)commissioningTimeout + pAKEVerifier:(NSData *)pAKEVerifier + discriminator:(uint16_t)discriminator + iterations:(uint32_t)iterations + salt:(NSData *)salt + passcodeID:(uint16_t)passcodeID + responseHandler:(ResponseHandler)responseHandler; +- (void)revokeCommissioning:(ResponseHandler)responseHandler; + +- (void)readAttributeClusterRevisionWithResponseHandler:(ResponseHandler)responseHandler; + +@end + /** * Cluster Application Basic * diff --git a/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.mm b/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.mm index 9176c8c97af057..79f41065774fd0 100644 --- a/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.mm +++ b/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.mm @@ -3759,6 +3759,133 @@ - (void)readAttributeClusterRevisionWithResponseHandler:(ResponseHandler)respons @end +@interface CHIPAdministratorCommissioning () +@property (readonly) Controller::AdministratorCommissioningCluster cppCluster; +@end + +@implementation CHIPAdministratorCommissioning + +- (Controller::ClusterBase *)getCluster +{ + return &_cppCluster; +} + +- (void)openBasicCommissioningWindow:(uint16_t)commissioningTimeout responseHandler:(ResponseHandler)responseHandler +{ + CHIPDefaultSuccessCallbackBridge * onSuccess = new CHIPDefaultSuccessCallbackBridge(responseHandler, [self callbackQueue]); + if (!onSuccess) { + responseHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); + return; + } + + CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(responseHandler, [self callbackQueue]); + if (!onFailure) { + delete onSuccess; + responseHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); + return; + } + + __block CHIP_ERROR err; + dispatch_sync([self chipWorkQueue], ^{ + err = self.cppCluster.OpenBasicCommissioningWindow(onSuccess->Cancel(), onFailure->Cancel(), commissioningTimeout); + }); + + if (err != CHIP_NO_ERROR) { + delete onSuccess; + delete onFailure; + responseHandler([CHIPError errorForCHIPErrorCode:err], nil); + } +} +- (void)openCommissioningWindow:(uint16_t)commissioningTimeout + pAKEVerifier:(NSData *)pAKEVerifier + discriminator:(uint16_t)discriminator + iterations:(uint32_t)iterations + salt:(NSData *)salt + passcodeID:(uint16_t)passcodeID + responseHandler:(ResponseHandler)responseHandler +{ + CHIPDefaultSuccessCallbackBridge * onSuccess = new CHIPDefaultSuccessCallbackBridge(responseHandler, [self callbackQueue]); + if (!onSuccess) { + responseHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); + return; + } + + CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(responseHandler, [self callbackQueue]); + if (!onFailure) { + delete onSuccess; + responseHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); + return; + } + + __block CHIP_ERROR err; + dispatch_sync([self chipWorkQueue], ^{ + err = self.cppCluster.OpenCommissioningWindow(onSuccess->Cancel(), onFailure->Cancel(), commissioningTimeout, + chip::ByteSpan((const uint8_t *) pAKEVerifier.bytes, pAKEVerifier.length), discriminator, iterations, + chip::ByteSpan((const uint8_t *) salt.bytes, salt.length), passcodeID); + }); + + if (err != CHIP_NO_ERROR) { + delete onSuccess; + delete onFailure; + responseHandler([CHIPError errorForCHIPErrorCode:err], nil); + } +} +- (void)revokeCommissioning:(ResponseHandler)responseHandler +{ + CHIPDefaultSuccessCallbackBridge * onSuccess = new CHIPDefaultSuccessCallbackBridge(responseHandler, [self callbackQueue]); + if (!onSuccess) { + responseHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); + return; + } + + CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(responseHandler, [self callbackQueue]); + if (!onFailure) { + delete onSuccess; + responseHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); + return; + } + + __block CHIP_ERROR err; + dispatch_sync([self chipWorkQueue], ^{ + err = self.cppCluster.RevokeCommissioning(onSuccess->Cancel(), onFailure->Cancel()); + }); + + if (err != CHIP_NO_ERROR) { + delete onSuccess; + delete onFailure; + responseHandler([CHIPError errorForCHIPErrorCode:err], nil); + } +} + +- (void)readAttributeClusterRevisionWithResponseHandler:(ResponseHandler)responseHandler +{ + CHIPInt16uAttributeCallbackBridge * onSuccess = new CHIPInt16uAttributeCallbackBridge(responseHandler, [self callbackQueue]); + if (!onSuccess) { + responseHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); + return; + } + + CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(responseHandler, [self callbackQueue]); + if (!onFailure) { + delete onSuccess; + responseHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); + return; + } + + __block CHIP_ERROR err; + dispatch_sync([self chipWorkQueue], ^{ + err = self.cppCluster.ReadAttributeClusterRevision(onSuccess->Cancel(), onFailure->Cancel()); + }); + + if (err != CHIP_NO_ERROR) { + delete onSuccess; + delete onFailure; + responseHandler([CHIPError errorForCHIPErrorCode:err], nil); + } +} + +@end + @interface CHIPApplicationBasic () @property (readonly) Controller::ApplicationBasicCluster cppCluster; @end diff --git a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m index 52cf831d4d74e8..cb7082aacf21da 100644 --- a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m @@ -5276,6 +5276,27 @@ - (void)testSendClusterAccountLoginReadAttributeClusterRevisionWithResponseHandl [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } +- (void)testSendClusterAdministratorCommissioningReadAttributeClusterRevisionWithResponseHandler +{ + XCTestExpectation * expectation = + [self expectationWithDescription:@"AdministratorCommissioningReadAttributeClusterRevisionWithResponseHandler"]; + + CHIPDevice * device = GetPairedDevice(kDeviceId); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPAdministratorCommissioning * cluster = [[CHIPAdministratorCommissioning alloc] initWithDevice:device + endpoint:1 + queue:queue]; + XCTAssertNotNil(cluster); + + [cluster readAttributeClusterRevisionWithResponseHandler:^(NSError * err, NSDictionary * values) { + NSLog(@"AdministratorCommissioning ClusterRevision Error: %@", err); + XCTAssertEqual(err.code, 0); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} + - (void)testSendClusterApplicationBasicReadAttributeVendorNameWithResponseHandler { XCTestExpectation * expectation = From beee5b2ec18dfb4ad2ced9742e7df5625dace033 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 27 Jul 2021 15:56:49 -0700 Subject: [PATCH 03/10] implement cluster logic --- examples/all-clusters-app/esp32/main/main.cpp | 2 +- .../administrator-commissioning-server.cpp | 42 ++++-- src/app/server/RendezvousServer.cpp | 12 +- src/app/server/RendezvousServer.h | 5 +- src/app/server/Server.cpp | 142 +++++++++--------- src/app/server/Server.h | 13 +- src/controller/CHIPDevice.cpp | 48 +++--- src/controller/CHIPDevice.h | 16 +- src/protocols/secure_channel/PASESession.cpp | 58 ++++--- src/protocols/secure_channel/PASESession.h | 30 ++-- .../secure_channel/tests/TestPASESession.cpp | 12 +- 11 files changed, 219 insertions(+), 161 deletions(-) diff --git a/examples/all-clusters-app/esp32/main/main.cpp b/examples/all-clusters-app/esp32/main/main.cpp index b4c6da1f2cbb24..642b00f026bcc0 100644 --- a/examples/all-clusters-app/esp32/main/main.cpp +++ b/examples/all-clusters-app/esp32/main/main.cpp @@ -348,7 +348,7 @@ class SetupListModel : public ListScreen::Model else if (i == 2) { app::Mdns::AdvertiseCommissionableNode(); - OpenDefaultPairingWindow(ResetFabrics::kYes, PairingWindowAdvertisement::kMdns); + OpenDefaultPairingWindow(ResetFabrics::kYes, kNoCommissioningTimeout, PairingWindowAdvertisement::kMdns); } } diff --git a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp index c95195c1d2a3a8..7e0920c9b77a10 100644 --- a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp +++ b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp @@ -21,15 +21,9 @@ ***************************************************************************/ #include -#include -#include -#include -#include -#include #include #include #include -#include #include using namespace chip; @@ -39,7 +33,22 @@ bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(app uint16_t Discriminator, uint32_t Iterations, ByteSpan Salt, uint16_t PasscodeID) { - EmberAfStatus status = EMBER_ZCL_STATUS_FAILURE; + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + PASEVerifier verifier; + ChipLogProgress(Zcl, "Received command to open commissioning window"); + VerifyOrExit(!IsPairingWindowOpen(), status = EMBER_ZCL_STATUS_FAILURE); + VerifyOrExit(sizeof(verifier) == PAKEVerifier.size(), status = EMBER_ZCL_STATUS_FAILURE); + memcpy(&verifier[0][0], PAKEVerifier.data(), PAKEVerifier.size()); + VerifyOrExit(OpenPairingWindowUsingVerifier(CommissioningTimeout, Discriminator, verifier, Iterations, Salt, PasscodeID) == + CHIP_NO_ERROR, + status = EMBER_ZCL_STATUS_FAILURE); + ChipLogProgress(Zcl, "Commissioning window is now open"); + +exit: + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogError(Zcl, "Failed to open commissioning window. Status %d", status); + } emberAfSendImmediateDefaultResponse(status); return true; } @@ -47,14 +56,27 @@ bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(app bool emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(app::CommandHandler * commandObj, uint16_t CommissioningTimeout) { - EmberAfStatus status = EMBER_ZCL_STATUS_FAILURE; + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + ChipLogProgress(Zcl, "Received command to open basic commissioning window"); + VerifyOrExit(!IsPairingWindowOpen(), status = EMBER_ZCL_STATUS_FAILURE); + VerifyOrExit(OpenDefaultPairingWindow(ResetFabrics::kNo, CommissioningTimeout) == CHIP_NO_ERROR, + status = EMBER_ZCL_STATUS_FAILURE); + ChipLogProgress(Zcl, "Commissioning window is now open"); + +exit: + if (status != EMBER_ZCL_STATUS_SUCCESS) + { + ChipLogError(Zcl, "Failed to open commissioning window. Status %d", status); + } emberAfSendImmediateDefaultResponse(status); return true; } bool emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(app::CommandHandler * commandObj) { - EmberAfStatus status = EMBER_ZCL_STATUS_FAILURE; - emberAfSendImmediateDefaultResponse(status); + ChipLogProgress(Zcl, "Received command to close commissioning window"); + ClosePairingWindow(); + ChipLogProgress(Zcl, "Commissioning window is now closed"); + emberAfSendImmediateDefaultResponse(EMBER_ZCL_STATUS_SUCCESS); return true; } diff --git a/src/app/server/RendezvousServer.cpp b/src/app/server/RendezvousServer.cpp index cff03e3790894f..58b6b52b01300a 100644 --- a/src/app/server/RendezvousServer.cpp +++ b/src/app/server/RendezvousServer.cpp @@ -42,8 +42,6 @@ void OnPlatformEventWrapper(const DeviceLayer::ChipDeviceEvent * event, intptr_t server->OnPlatformEvent(event); } } // namespace -static constexpr uint32_t kSpake2p_Iteration_Count = 100; -static const char * kSpake2pKeyExchangeSalt = "SPAKE2P Key Salt"; void RendezvousServer::OnPlatformEvent(const DeviceLayer::ChipDeviceEvent * event) { @@ -67,7 +65,8 @@ void RendezvousServer::OnPlatformEvent(const DeviceLayer::ChipDeviceEvent * even } } -CHIP_ERROR RendezvousServer::WaitForPairing(const RendezvousParameters & params, Messaging::ExchangeManager * exchangeManager, +CHIP_ERROR RendezvousServer::WaitForPairing(const RendezvousParameters & params, uint32_t pbkdf2IterCount, const ByteSpan & salt, + uint16_t passcodeID, Messaging::ExchangeManager * exchangeManager, TransportMgrBase * transportMgr, SecureSessionMgr * sessionMgr, Transport::FabricInfo * fabric) { @@ -106,13 +105,12 @@ CHIP_ERROR RendezvousServer::WaitForPairing(const RendezvousParameters & params, if (params.HasPASEVerifier()) { - ReturnErrorOnFailure(mPairingSession.WaitForPairing(params.GetPASEVerifier(), keyID, this)); + ReturnErrorOnFailure( + mPairingSession.WaitForPairing(params.GetPASEVerifier(), pbkdf2IterCount, salt, passcodeID, keyID, this)); } else { - ReturnErrorOnFailure(mPairingSession.WaitForPairing(params.GetSetupPINCode(), kSpake2p_Iteration_Count, - reinterpret_cast(kSpake2pKeyExchangeSalt), - strlen(kSpake2pKeyExchangeSalt), keyID, this)); + ReturnErrorOnFailure(mPairingSession.WaitForPairing(params.GetSetupPINCode(), pbkdf2IterCount, salt, keyID, this)); } ReturnErrorOnFailure(mPairingSession.MessageDispatch().Init(transportMgr)); diff --git a/src/app/server/RendezvousServer.h b/src/app/server/RendezvousServer.h index ad7fc8fefdc362..df55bcf7697b5f 100644 --- a/src/app/server/RendezvousServer.h +++ b/src/app/server/RendezvousServer.h @@ -29,8 +29,9 @@ namespace chip { class RendezvousServer : public SessionEstablishmentDelegate { public: - CHIP_ERROR WaitForPairing(const RendezvousParameters & params, Messaging::ExchangeManager * exchangeManager, - TransportMgrBase * transportMgr, SecureSessionMgr * sessionMgr, Transport::FabricInfo * fabric); + CHIP_ERROR WaitForPairing(const RendezvousParameters & params, uint32_t pbkdf2IterCount, const ByteSpan & salt, + uint16_t passcodeID, Messaging::ExchangeManager * exchangeManager, TransportMgrBase * transportMgr, + SecureSessionMgr * sessionMgr, Transport::FabricInfo * fabric); CHIP_ERROR Init(AppDelegate * delegate, PersistentStorageDelegate * storage, SessionIDAllocator * idAllocator) { diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 9592972add22f6..41c4203484288f 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -247,6 +247,7 @@ class DeviceDiscriminatorCache DeviceDiscriminatorCache gDeviceDiscriminatorCache; FabricTable gFabrics; FabricIndex gNextAvailableFabricIndex = 0; +bool gPairingWindowOpen = false; class ServerRendezvousAdvertisementDelegate : public RendezvousAdvertisementDelegate { @@ -261,12 +262,15 @@ class ServerRendezvousAdvertisementDelegate : public RendezvousAdvertisementDele { mDelegate->OnPairingWindowOpened(); } + gPairingWindowOpen = true; return CHIP_NO_ERROR; } CHIP_ERROR StopAdvertisement() const override { gDeviceDiscriminatorCache.RestoreDiscriminator(); + gPairingWindowOpen = false; + if (isBLE) { ReturnErrorOnFailure(chip::DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(false)); @@ -303,29 +307,6 @@ CASEServer gCASEServer; Messaging::ExchangeManager gExchangeMgr; ServerRendezvousAdvertisementDelegate gAdvDelegate; -static CHIP_ERROR OpenPairingWindowUsingVerifier(uint16_t discriminator, PASEVerifier & verifier) -{ - RendezvousParameters params; - - ReturnErrorOnFailure(gDeviceDiscriminatorCache.UpdateDiscriminator(discriminator)); - -#if CONFIG_NETWORK_LAYER_BLE - params.SetPASEVerifier(verifier) - .SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer()) - .SetPeerAddress(Transport::PeerAddress::BLE()) - .SetAdvertisementDelegate(&gAdvDelegate); -#else - params.SetPASEVerifier(verifier); -#endif // CONFIG_NETWORK_LAYER_BLE - - FabricIndex fabricIndex = gNextAvailableFabricIndex; - FabricInfo * fabricInfo = gFabrics.AssignFabricIndex(fabricIndex); - VerifyOrReturnError(fabricInfo != nullptr, CHIP_ERROR_NO_MEMORY); - gNextAvailableFabricIndex++; - - return gRendezvousServer.WaitForPairing(std::move(params), &gExchangeMgr, &gTransports, &gSessions, fabricInfo); -} - class ServerCallback : public ExchangeDelegate { public: @@ -345,52 +326,7 @@ class ServerCallback : public ExchangeDelegate ChipLogProgress(AppServer, "Packet received from Node 0x" ChipLogFormatX64 ": %u bytes", ChipLogValueX64(packetHeader.GetSourceNodeId().Value()), buffer->DataLength()); - // TODO: This code is temporary, and must be updated to use the Cluster API. - // Issue: https://github.com/project-chip/connectedhomeip/issues/4725 - if (payloadHeader.HasProtocol(chip::Protocols::ServiceProvisioning::Id)) - { - uint32_t timeout; - uint16_t discriminator; - PASEVerifier verifier; - - ChipLogProgress(AppServer, "Received service provisioning message. Treating it as OpenPairingWindow request"); - chip::System::PacketBufferTLVReader reader; - reader.Init(std::move(buffer)); - reader.ImplicitProfileId = chip::Protocols::ServiceProvisioning::Id.ToTLVProfileId(); - - SuccessOrExit(reader.Next(kTLVType_UnsignedInteger, TLV::ProfileTag(reader.ImplicitProfileId, 1))); - SuccessOrExit(reader.Get(timeout)); - - err = reader.Next(kTLVType_UnsignedInteger, TLV::ProfileTag(reader.ImplicitProfileId, 2)); - if (err == CHIP_NO_ERROR) - { - SuccessOrExit(reader.Get(discriminator)); - - err = reader.Next(kTLVType_ByteString, TLV::ProfileTag(reader.ImplicitProfileId, 3)); - if (err == CHIP_NO_ERROR) - { - SuccessOrExit(reader.GetBytes(reinterpret_cast(verifier), sizeof(verifier))); - } - } - - ChipLogProgress(AppServer, "Pairing Window timeout %" PRIu32 " seconds", timeout); - - if (err != CHIP_NO_ERROR) - { - SuccessOrExit(err = OpenDefaultPairingWindow(ResetFabrics::kNo)); - } - else - { - ChipLogProgress(AppServer, "Pairing Window discriminator %d", discriminator); - err = OpenPairingWindowUsingVerifier(discriminator, verifier); - SuccessOrExit(err); - } - ChipLogProgress(AppServer, "Opened the pairing window"); - } - else - { - HandleDataModelMessage(exchangeContext, std::move(buffer)); - } + HandleDataModelMessage(exchangeContext, std::move(buffer)); exit: return err; @@ -423,9 +359,15 @@ chip::Protocols::UserDirectedCommissioning::UserDirectedCommissioningClient gUDC #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT +void HandlePairingWindowTimeout(System::Layer * aSystemLayer, void * aAppState, CHIP_ERROR aError) +{ + ClosePairingWindow(); +} + } // namespace -CHIP_ERROR OpenDefaultPairingWindow(ResetFabrics resetFabrics, chip::PairingWindowAdvertisement advertisementMode) +CHIP_ERROR OpenDefaultPairingWindow(ResetFabrics resetFabrics, uint16_t commissioningTimeoutSeconds, + chip::PairingWindowAdvertisement advertisementMode) { // TODO(cecille): If this is re-called when the window is already open, what should happen? gDeviceDiscriminatorCache.RestoreDiscriminator(); @@ -460,7 +402,65 @@ CHIP_ERROR OpenDefaultPairingWindow(ResetFabrics resetFabrics, chip::PairingWind VerifyOrReturnError(fabricInfo != nullptr, CHIP_ERROR_NO_MEMORY); gNextAvailableFabricIndex++; - return gRendezvousServer.WaitForPairing(std::move(params), &gExchangeMgr, &gTransports, &gSessions, fabricInfo); + ReturnErrorOnFailure(gRendezvousServer.WaitForPairing( + std::move(params), kSpake2p_Iteration_Count, + ByteSpan(reinterpret_cast(kSpake2pKeyExchangeSalt), strlen(kSpake2pKeyExchangeSalt)), 0, + &gExchangeMgr, &gTransports, &gSessions, fabricInfo)); + + if (commissioningTimeoutSeconds != kNoCommissioningTimeout) + { + ReturnErrorOnFailure( + DeviceLayer::SystemLayer.StartTimer(commissioningTimeoutSeconds * 1000, HandlePairingWindowTimeout, nullptr)); + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR OpenPairingWindowUsingVerifier(uint16_t commissioningTimeoutSeconds, uint16_t discriminator, PASEVerifier & verifier, + uint32_t iterations, ByteSpan salt, uint16_t passcodeID) +{ + RendezvousParameters params; + + ReturnErrorOnFailure(gDeviceDiscriminatorCache.UpdateDiscriminator(discriminator)); + +#if CONFIG_NETWORK_LAYER_BLE + params.SetPASEVerifier(verifier) + .SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer()) + .SetPeerAddress(Transport::PeerAddress::BLE()) + .SetAdvertisementDelegate(&gAdvDelegate); +#else + params.SetPASEVerifier(verifier); +#endif // CONFIG_NETWORK_LAYER_BLE + + FabricIndex fabricIndex = gNextAvailableFabricIndex; + FabricInfo * fabricInfo = gFabrics.AssignFabricIndex(fabricIndex); + VerifyOrReturnError(fabricInfo != nullptr, CHIP_ERROR_NO_MEMORY); + gNextAvailableFabricIndex++; + + ReturnErrorOnFailure(gRendezvousServer.WaitForPairing(std::move(params), iterations, salt, passcodeID, &gExchangeMgr, + &gTransports, &gSessions, fabricInfo)); + + if (commissioningTimeoutSeconds != kNoCommissioningTimeout) + { + ReturnErrorOnFailure( + DeviceLayer::SystemLayer.StartTimer(commissioningTimeoutSeconds * 1000, HandlePairingWindowTimeout, nullptr)); + } + + return CHIP_NO_ERROR; +} + +void ClosePairingWindow() +{ + if (gPairingWindowOpen) + { + ChipLogProgress(AppServer, "Closing pairing window"); + gRendezvousServer.Cleanup(); + } +} + +bool IsPairingWindowOpen() +{ + return gPairingWindowOpen; } // The function will initialize datamodel handler and then start the server diff --git a/src/app/server/Server.h b/src/app/server/Server.h index af3b964dd45cf3..94f087f61e7a27 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -71,8 +72,18 @@ enum class PairingWindowAdvertisement } // namespace chip +constexpr uint16_t kNoCommissioningTimeout = UINT16_MAX; + /** * Open the pairing window using default configured parameters. */ -CHIP_ERROR OpenDefaultPairingWindow(chip::ResetFabrics resetFabrics, +CHIP_ERROR OpenDefaultPairingWindow(chip::ResetFabrics resetFabrics, uint16_t commissioningTimeoutSeconds = kNoCommissioningTimeout, chip::PairingWindowAdvertisement advertisementMode = chip::PairingWindowAdvertisement::kBle); + +CHIP_ERROR OpenPairingWindowUsingVerifier(uint16_t commissioningTimeoutSeconds, uint16_t discriminator, + chip::PASEVerifier & verifier, uint32_t iterations, chip::ByteSpan salt, + uint16_t passcodeID); + +void ClosePairingWindow(); + +bool IsPairingWindowOpen(); diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index 743261d67375a1..8d77b8a17e5bef 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -26,6 +26,8 @@ #include +#include + #if CONFIG_DEVICE_LAYER #include #endif @@ -344,36 +346,40 @@ CHIP_ERROR Device::OnMessageReceived(Messaging::ExchangeContext * exchange, cons void Device::OnResponseTimeout(Messaging::ExchangeContext * ec) {} -CHIP_ERROR Device::OpenPairingWindow(uint32_t timeout, PairingWindowOption option, SetupPayload & setupPayload) +void Device::OnOpenPairingWindowSuccessResponse(void * context) { - // TODO: This code is temporary, and must be updated to use the Cluster API. - // Issue: https://github.com/project-chip/connectedhomeip/issues/4725 + ChipLogProgress(Controller, "Successfully opened pairing window on the device"); +} - // Construct and send "open pairing window" message to the device - System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize); - System::PacketBufferTLVWriter writer; +void Device::OnOpenPairingWindowFailureResponse(void * context, uint8_t status) +{ + ChipLogError(Controller, "Failed to open pairing window on the device. Status %d", status); +} - writer.Init(std::move(buf)); - writer.ImplicitProfileId = chip::Protocols::ServiceProvisioning::Id.ToTLVProfileId(); +CHIP_ERROR Device::OpenPairingWindow(uint16_t timeout, PairingWindowOption option, SetupPayload & setupPayload) +{ + chip::Controller::AdministratorCommissioningCluster cluster; + cluster.Associate(this, 0); - ReturnErrorOnFailure(writer.Put(TLV::ProfileTag(writer.ImplicitProfileId, 1), timeout)); + Callback::Cancelable * successCallback = mOpenPairingSuccessCallback.Cancel(); + Callback::Cancelable * failureCallback = mOpenPairingFailureCallback.Cancel(); if (option != PairingWindowOption::kOriginalSetupCode) { - ReturnErrorOnFailure(writer.Put(TLV::ProfileTag(writer.ImplicitProfileId, 2), setupPayload.discriminator)); - - PASEVerifier verifier; bool randomSetupPIN = (option == PairingWindowOption::kTokenWithRandomPIN); - ReturnErrorOnFailure(PASESession::GeneratePASEVerifier(verifier, randomSetupPIN, setupPayload.setUpPINCode)); - ReturnErrorOnFailure(writer.PutBytes(TLV::ProfileTag(writer.ImplicitProfileId, 3), - reinterpret_cast(verifier), sizeof(verifier))); - } - - System::PacketBufferHandle outBuffer; - ReturnErrorOnFailure(writer.Finalize(&outBuffer)); + PASEVerifier verifier; + ByteSpan salt(reinterpret_cast(kSpake2pKeyExchangeSalt), strlen(kSpake2pKeyExchangeSalt)); + ReturnErrorOnFailure( + PASESession::GeneratePASEVerifier(verifier, kSpake2p_Iteration_Count, salt, randomSetupPIN, setupPayload.setUpPINCode)); - ReturnErrorOnFailure(SendMessage(Protocols::ServiceProvisioning::MsgType::ServiceProvisioningRequest, - Messaging::SendMessageFlags::kNone, std::move(outBuffer))); + ReturnErrorOnFailure( + cluster.OpenCommissioningWindow(successCallback, failureCallback, timeout, ByteSpan(&verifier[0][0], sizeof(verifier)), + setupPayload.discriminator, kSpake2p_Iteration_Count, salt, mPAKEVerifierID++)); + } + else + { + ReturnErrorOnFailure(cluster.OpenBasicCommissioningWindow(successCallback, failureCallback, timeout)); + } setupPayload.version = 0; setupPayload.rendezvousInformation = RendezvousInformationFlags(RendezvousInformationFlag::kBLE); diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index eea68fcee71dcc..2e896a1d60c92b 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -99,7 +100,10 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta { public: ~Device(); - Device() = default; + Device() : + mOpenPairingSuccessCallback(OnOpenPairingWindowSuccessResponse, this), + mOpenPairingFailureCallback(OnOpenPairingWindowFailureResponse, this) + {} Device(const Device &) = delete; enum class PairingWindowOption @@ -301,7 +305,7 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta * * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error */ - CHIP_ERROR OpenPairingWindow(uint32_t timeout, PairingWindowOption option, SetupPayload & setupPayload); + CHIP_ERROR OpenPairingWindow(uint16_t timeout, PairingWindowOption option, SetupPayload & setupPayload); /** * In case there exists an open session to the device, mark it as expired. @@ -480,6 +484,9 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta CHIP_ERROR WarmupCASESession(); + static void OnOpenPairingWindowSuccessResponse(void * context); + static void OnOpenPairingWindowFailureResponse(void * context, uint8_t status); + uint16_t mListenPort; FabricIndex mFabricIndex = Transport::kUndefinedFabricIndex; @@ -502,8 +509,13 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta SessionIDAllocator * mIDAllocator = nullptr; + uint16_t mPAKEVerifierID = 1; + Callback::CallbackDeque mConnectionSuccess; Callback::CallbackDeque mConnectionFailure; + + Callback::Callback mOpenPairingSuccessCallback; + Callback::Callback mOpenPairingFailureCallback; }; /** diff --git a/src/protocols/secure_channel/PASESession.cpp b/src/protocols/secure_channel/PASESession.cpp index fc8dbf2cee994e..a86b93b0efed7c 100644 --- a/src/protocols/secure_channel/PASESession.cpp +++ b/src/protocols/secure_channel/PASESession.cpp @@ -54,8 +54,7 @@ const char * kSpake2pContext = "CHIP PAKE V1 Commissioning"; const char * kSpake2pI2RSessionInfo = "Commissioning I2R Key"; const char * kSpake2pR2ISessionInfo = "Commissioning R2I Key"; -static constexpr uint32_t kSpake2p_Iteration_Count = 100; -static const char * kSpake2pKeyExchangeSalt = "SPAKE2P Key Salt"; +const char * kSpake2pKeyExchangeSalt = "SPAKE2P Key Salt"; // Wait at most 30 seconds for the response from the peer. // This timeout value assumes the underlying transport is reliable. @@ -198,18 +197,23 @@ CHIP_ERROR PASESession::Init(uint16_t myKeyId, uint32_t setupCode, SessionEstabl return CHIP_NO_ERROR; } -CHIP_ERROR PASESession::ComputePASEVerifier(uint32_t setUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen, +CHIP_ERROR PASESession::ComputePASEVerifier(uint32_t setUpPINCode, uint32_t pbkdf2IterCount, const ByteSpan & salt, PASEVerifier & verifier) { + ReturnErrorCodeIf(salt.empty(), CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorCodeIf(salt.data() == nullptr, CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorCodeIf(setUpPINCode >= (1 << kSetupPINCodeFieldLengthInBits), CHIP_ERROR_INVALID_ARGUMENT); + PBKDF2_sha256_crypto mPBKDF; uint8_t littleEndianSetupPINCode[sizeof(uint32_t)]; Encoding::LittleEndian::Put32(littleEndianSetupPINCode, setUpPINCode); - return mPBKDF.pbkdf2_sha256(littleEndianSetupPINCode, sizeof(littleEndianSetupPINCode), salt, saltLen, pbkdf2IterCount, - sizeof(PASEVerifier), &verifier[0][0]); + return mPBKDF.pbkdf2_sha256(littleEndianSetupPINCode, sizeof(littleEndianSetupPINCode), salt.data(), salt.size(), + pbkdf2IterCount, sizeof(PASEVerifier), &verifier[0][0]); } -CHIP_ERROR PASESession::GeneratePASEVerifier(PASEVerifier & verifier, bool useRandomPIN, uint32_t & setupPIN) +CHIP_ERROR PASESession::GeneratePASEVerifier(PASEVerifier & verifier, uint32_t pbkdf2IterCount, const ByteSpan & salt, + bool useRandomPIN, uint32_t & setupPIN) { if (useRandomPIN) { @@ -218,17 +222,11 @@ CHIP_ERROR PASESession::GeneratePASEVerifier(PASEVerifier & verifier, bool useRa // Use only kSetupPINCodeFieldLengthInBits bits out of the code setupPIN &= ((1 << kSetupPINCodeFieldLengthInBits) - 1); } - else if (setupPIN >= (1 << kSetupPINCodeFieldLengthInBits)) - { - return CHIP_ERROR_INVALID_ARGUMENT; - } - return PASESession::ComputePASEVerifier(setupPIN, kSpake2p_Iteration_Count, - reinterpret_cast(kSpake2pKeyExchangeSalt), - strlen(kSpake2pKeyExchangeSalt), verifier); + return PASESession::ComputePASEVerifier(setupPIN, pbkdf2IterCount, salt, verifier); } -CHIP_ERROR PASESession::SetupSpake2p(uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen) +CHIP_ERROR PASESession::SetupSpake2p(uint32_t pbkdf2IterCount, const ByteSpan & salt) { uint8_t context[kSHA256_Hash_Length] = { 0, @@ -236,10 +234,7 @@ CHIP_ERROR PASESession::SetupSpake2p(uint32_t pbkdf2IterCount, const uint8_t * s if (mComputeVerifier) { - VerifyOrReturnError(salt != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(saltLen > 0, CHIP_ERROR_INVALID_ARGUMENT); - - ReturnErrorOnFailure(PASESession::ComputePASEVerifier(mSetupPINCode, pbkdf2IterCount, salt, saltLen, mPASEVerifier)); + ReturnErrorOnFailure(PASESession::ComputePASEVerifier(mSetupPINCode, pbkdf2IterCount, salt, mPASEVerifier)); } MutableByteSpan contextSpan{ context, sizeof(context) }; @@ -250,20 +245,20 @@ CHIP_ERROR PASESession::SetupSpake2p(uint32_t pbkdf2IterCount, const uint8_t * s return CHIP_NO_ERROR; } -CHIP_ERROR PASESession::WaitForPairing(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen, - uint16_t myKeyId, SessionEstablishmentDelegate * delegate) +CHIP_ERROR PASESession::WaitForPairing(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const ByteSpan & salt, uint16_t myKeyId, + SessionEstablishmentDelegate * delegate) { // Return early on error here, as we have not initalized any state yet - ReturnErrorCodeIf(salt == nullptr, CHIP_ERROR_INVALID_ARGUMENT); - ReturnErrorCodeIf(saltLen == 0, CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorCodeIf(salt.empty(), CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorCodeIf(salt.data() == nullptr, CHIP_ERROR_INVALID_ARGUMENT); CHIP_ERROR err = Init(myKeyId, mySetUpPINCode, delegate); // From here onwards, let's go to exit on error, as some state might have already // been initialized SuccessOrExit(err); - VerifyOrExit(CanCastTo(saltLen), err = CHIP_ERROR_INVALID_ARGUMENT); - mSaltLength = static_cast(saltLen); + VerifyOrExit(CanCastTo(salt.size()), err = CHIP_ERROR_INVALID_ARGUMENT); + mSaltLength = static_cast(salt.size()); if (mSalt != nullptr) { @@ -274,12 +269,13 @@ CHIP_ERROR PASESession::WaitForPairing(uint32_t mySetUpPINCode, uint32_t pbkdf2I mSalt = static_cast(chip::Platform::MemoryAlloc(mSaltLength)); VerifyOrExit(mSalt != nullptr, err = CHIP_ERROR_NO_MEMORY); - memmove(mSalt, salt, mSaltLength); + memmove(mSalt, salt.data(), mSaltLength); mIterationCount = pbkdf2IterCount; mNextExpectedMsg = Protocols::SecureChannel::MsgType::PBKDFParamRequest; mPairingComplete = false; + mPasscodeID = 0; ChipLogDetail(SecureChannel, "Waiting for PBKDF param request"); @@ -291,14 +287,14 @@ CHIP_ERROR PASESession::WaitForPairing(uint32_t mySetUpPINCode, uint32_t pbkdf2I return err; } -CHIP_ERROR PASESession::WaitForPairing(const PASEVerifier & verifier, uint16_t myKeyId, SessionEstablishmentDelegate * delegate) +CHIP_ERROR PASESession::WaitForPairing(const PASEVerifier & verifier, uint32_t pbkdf2IterCount, const ByteSpan & salt, + uint16_t passcodeID, uint16_t myKeyId, SessionEstablishmentDelegate * delegate) { - ReturnErrorOnFailure(WaitForPairing(0, kSpake2p_Iteration_Count, - reinterpret_cast(kSpake2pKeyExchangeSalt), - strlen(kSpake2pKeyExchangeSalt), myKeyId, delegate)); + ReturnErrorOnFailure(WaitForPairing(0, pbkdf2IterCount, salt, myKeyId, delegate)); memmove(&mPASEVerifier, verifier, sizeof(verifier)); mComputeVerifier = false; + mPasscodeID = passcodeID; return CHIP_NO_ERROR; } @@ -430,7 +426,7 @@ CHIP_ERROR PASESession::SendPBKDFParamResponse() // Update commissioning hash with the pbkdf2 param response that's being sent. ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ resp->Start(), resp->DataLength() })); - ReturnErrorOnFailure(SetupSpake2p(mIterationCount, mSalt, mSaltLength)); + ReturnErrorOnFailure(SetupSpake2p(mIterationCount, ByteSpan(mSalt, mSaltLength))); ReturnErrorOnFailure(mSpake2p.ComputeL(mPoint, &sizeof_point, &mPASEVerifier[1][0], kSpake2p_WS_Length)); mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2p1; @@ -476,7 +472,7 @@ CHIP_ERROR PASESession::HandlePBKDFParamResponse(const System::PacketBufferHandl err = mCommissioningHash.AddData(ByteSpan{ resp, resplen }); SuccessOrExit(err); - err = SetupSpake2p(static_cast(iterCount), msgptr, saltlen); + err = SetupSpake2p(static_cast(iterCount), ByteSpan(msgptr, saltlen)); SuccessOrExit(err); } diff --git a/src/protocols/secure_channel/PASESession.h b/src/protocols/secure_channel/PASESession.h index b2ec8e4f755ac2..4cdfa798860603 100644 --- a/src/protocols/secure_channel/PASESession.h +++ b/src/protocols/secure_channel/PASESession.h @@ -48,8 +48,10 @@ namespace chip { extern const char * kSpake2pI2RSessionInfo; extern const char * kSpake2pR2ISessionInfo; +extern const char * kSpake2pKeyExchangeSalt; constexpr uint16_t kPBKDFParamRandomNumberSize = 32; +constexpr uint32_t kSpake2p_Iteration_Count = 100; using namespace Crypto; @@ -86,26 +88,29 @@ class DLL_EXPORT PASESession : public Messaging::ExchangeDelegate, public Pairin * @param mySetUpPINCode Setup PIN code of the local device * @param pbkdf2IterCount Iteration count for PBKDF2 function * @param salt Salt to be used for SPAKE2P operation - * @param saltLen Length of salt * @param myKeyId Key ID to be assigned to the secure session on the peer node * @param delegate Callback object * * @return CHIP_ERROR The result of initialization */ - CHIP_ERROR WaitForPairing(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen, - uint16_t myKeyId, SessionEstablishmentDelegate * delegate); + CHIP_ERROR WaitForPairing(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const ByteSpan & salt, uint16_t myKeyId, + SessionEstablishmentDelegate * delegate); /** * @brief * Initialize using PASE verifier and wait for pairing requests. * * @param verifier PASE verifier to be used for SPAKE2P pairing + * @param pbkdf2IterCount Iteration count for PBKDF2 function + * @param salt Salt to be used for SPAKE2P operation + * @param passcodeID Passcode ID assigned by the administrator to this PASE verifier * @param myKeyId Key ID to be assigned to the secure session on the peer node * @param delegate Callback object * * @return CHIP_ERROR The result of initialization */ - CHIP_ERROR WaitForPairing(const PASEVerifier & verifier, uint16_t myKeyId, SessionEstablishmentDelegate * delegate); + CHIP_ERROR WaitForPairing(const PASEVerifier & verifier, uint32_t pbkdf2IterCount, const ByteSpan & salt, uint16_t passcodeID, + uint16_t myKeyId, SessionEstablishmentDelegate * delegate); /** * @brief @@ -129,13 +134,16 @@ class DLL_EXPORT PASESession : public Messaging::ExchangeDelegate, public Pairin * @brief * Generate a new PASE verifier. * - * @param verifier The generated PASE verifier - * @param useRandomPIN Generate a random setup PIN, if true. Else, use the provided PIN - * @param setupPIN Provided setup PIN (if useRandomPIN is false), or the generated PIN + * @param verifier The generated PASE verifier + * @param pbkdf2IterCount Iteration count for PBKDF2 function + * @param salt Salt to be used for SPAKE2P operation + * @param useRandomPIN Generate a random setup PIN, if true. Else, use the provided PIN + * @param setupPIN Provided setup PIN (if useRandomPIN is false), or the generated PIN * * @return CHIP_ERROR The result of PASE verifier generation */ - static CHIP_ERROR GeneratePASEVerifier(PASEVerifier & verifier, bool useRandomPIN, uint32_t & setupPIN); + static CHIP_ERROR GeneratePASEVerifier(PASEVerifier & verifier, uint32_t pbkdf2IterCount, const ByteSpan & salt, + bool useRandomPIN, uint32_t & setupPIN); /** * @brief @@ -246,10 +254,10 @@ class DLL_EXPORT PASESession : public Messaging::ExchangeDelegate, public Pairin CHIP_ERROR ValidateReceivedMessage(Messaging::ExchangeContext * exchange, const PacketHeader & packetHeader, const PayloadHeader & payloadHeader, System::PacketBufferHandle && msg); - static CHIP_ERROR ComputePASEVerifier(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen, + static CHIP_ERROR ComputePASEVerifier(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const ByteSpan & salt, PASEVerifier & verifier); - CHIP_ERROR SetupSpake2p(uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen); + CHIP_ERROR SetupSpake2p(uint32_t pbkdf2IterCount, const ByteSpan & salt); CHIP_ERROR SendPBKDFParamRequest(); CHIP_ERROR HandlePBKDFParamRequest(const System::PacketBufferHandle & msg); @@ -282,6 +290,8 @@ class DLL_EXPORT PASESession : public Messaging::ExchangeDelegate, public Pairin /* w0s and w1s */ PASEVerifier mPASEVerifier; + uint16_t mPasscodeID = 0; + uint32_t mSetupPINCode; bool mComputeVerifier = true; diff --git a/src/protocols/secure_channel/tests/TestPASESession.cpp b/src/protocols/secure_channel/tests/TestPASESession.cpp index d57b7f0f9b3d93..fbbdbfd7b6835a 100644 --- a/src/protocols/secure_channel/tests/TestPASESession.cpp +++ b/src/protocols/secure_channel/tests/TestPASESession.cpp @@ -106,10 +106,12 @@ void SecurePairingWaitTest(nlTestSuite * inSuite, void * inContext) gLoopback.Reset(); - NL_TEST_ASSERT(inSuite, pairing.WaitForPairing(1234, 500, nullptr, 0, 0, &delegate) == CHIP_ERROR_INVALID_ARGUMENT); + NL_TEST_ASSERT(inSuite, pairing.WaitForPairing(1234, 500, ByteSpan(nullptr, 0), 0, &delegate) == CHIP_ERROR_INVALID_ARGUMENT); NL_TEST_ASSERT(inSuite, - pairing.WaitForPairing(1234, 500, (const uint8_t *) "saltSalt", 8, 0, nullptr) == CHIP_ERROR_INVALID_ARGUMENT); - NL_TEST_ASSERT(inSuite, pairing.WaitForPairing(1234, 500, (const uint8_t *) "saltSalt", 8, 0, &delegate) == CHIP_NO_ERROR); + pairing.WaitForPairing(1234, 500, ByteSpan((const uint8_t *) "saltSalt", 8), 0, nullptr) == + CHIP_ERROR_INVALID_ARGUMENT); + NL_TEST_ASSERT(inSuite, + pairing.WaitForPairing(1234, 500, ByteSpan((const uint8_t *) "saltSalt", 8), 0, &delegate) == CHIP_NO_ERROR); } void SecurePairingStartTest(nlTestSuite * inSuite, void * inContext) @@ -185,7 +187,7 @@ void SecurePairingHandshakeTestCommon(nlTestSuite * inSuite, void * inContext, P Protocols::SecureChannel::MsgType::PBKDFParamRequest, &pairingAccessory) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, - pairingAccessory.WaitForPairing(1234, 500, (const uint8_t *) "saltSALT", 8, 0, &delegateAccessory) == + pairingAccessory.WaitForPairing(1234, 500, ByteSpan((const uint8_t *) "saltSALT", 8), 0, &delegateAccessory) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, pairingCommissioner.Pair(Transport::PeerAddress(Transport::Type::kBle), 1234, 0, contextCommissioner, @@ -256,7 +258,7 @@ void SecurePairingFailedHandshake(nlTestSuite * inSuite, void * inContext) Protocols::SecureChannel::MsgType::PBKDFParamRequest, &pairingAccessory) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, - pairingAccessory.WaitForPairing(1234, 500, (const uint8_t *) "saltSALT", 8, 0, &delegateAccessory) == + pairingAccessory.WaitForPairing(1234, 500, ByteSpan((const uint8_t *) "saltSALT", 8), 0, &delegateAccessory) == CHIP_NO_ERROR); NL_TEST_ASSERT(inSuite, pairingCommissioner.Pair(Transport::PeerAddress(Transport::Type::kBle), 4321, 0, contextCommissioner, From 0cf2559fd3d34ca3c77011151c5d7b5d6cac0cd6 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Thu, 29 Jul 2021 08:20:39 -0700 Subject: [PATCH 04/10] address review comments --- .../administrator-commissioning-server.cpp | 25 +++++++++++-------- src/app/server/Server.cpp | 4 +-- src/controller/CHIPDevice.cpp | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp index 7e0920c9b77a10..6ba164c83227b0 100644 --- a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp +++ b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp @@ -28,18 +28,19 @@ using namespace chip; -bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(app::CommandHandler * commandObj, - uint16_t CommissioningTimeout, ByteSpan PAKEVerifier, - uint16_t Discriminator, uint32_t Iterations, - ByteSpan Salt, uint16_t PasscodeID) +bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(chip::EndpointId endpoint, + app::CommandHandler * commandObj, + uint16_t commissioningTimeout, ByteSpan pakeVerifier, + uint16_t discriminator, uint32_t iterations, + ByteSpan salt, uint16_t passcodeID) { EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; PASEVerifier verifier; ChipLogProgress(Zcl, "Received command to open commissioning window"); VerifyOrExit(!IsPairingWindowOpen(), status = EMBER_ZCL_STATUS_FAILURE); - VerifyOrExit(sizeof(verifier) == PAKEVerifier.size(), status = EMBER_ZCL_STATUS_FAILURE); - memcpy(&verifier[0][0], PAKEVerifier.data(), PAKEVerifier.size()); - VerifyOrExit(OpenPairingWindowUsingVerifier(CommissioningTimeout, Discriminator, verifier, Iterations, Salt, PasscodeID) == + VerifyOrExit(sizeof(verifier) == pakeVerifier.size(), status = EMBER_ZCL_STATUS_FAILURE); + memcpy(&verifier[0][0], pakeVerifier.data(), pakeVerifier.size()); + VerifyOrExit(OpenPairingWindowUsingVerifier(commissioningTimeout, discriminator, verifier, iterations, salt, passcodeID) == CHIP_NO_ERROR, status = EMBER_ZCL_STATUS_FAILURE); ChipLogProgress(Zcl, "Commissioning window is now open"); @@ -53,13 +54,14 @@ bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(app return true; } -bool emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(app::CommandHandler * commandObj, - uint16_t CommissioningTimeout) +bool emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(chip::EndpointId endpoint, + app::CommandHandler * commandObj, + uint16_t commissioningTimeout) { EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; ChipLogProgress(Zcl, "Received command to open basic commissioning window"); VerifyOrExit(!IsPairingWindowOpen(), status = EMBER_ZCL_STATUS_FAILURE); - VerifyOrExit(OpenDefaultPairingWindow(ResetFabrics::kNo, CommissioningTimeout) == CHIP_NO_ERROR, + VerifyOrExit(OpenDefaultPairingWindow(ResetFabrics::kNo, commissioningTimeout) == CHIP_NO_ERROR, status = EMBER_ZCL_STATUS_FAILURE); ChipLogProgress(Zcl, "Commissioning window is now open"); @@ -72,7 +74,8 @@ bool emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallbac return true; } -bool emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(app::CommandHandler * commandObj) +bool emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(chip::EndpointId endpoint, + app::CommandHandler * commandObj) { ChipLogProgress(Zcl, "Received command to close commissioning window"); ClosePairingWindow(); diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 41c4203484288f..fc47d58daea370 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -404,8 +404,8 @@ CHIP_ERROR OpenDefaultPairingWindow(ResetFabrics resetFabrics, uint16_t commissi ReturnErrorOnFailure(gRendezvousServer.WaitForPairing( std::move(params), kSpake2p_Iteration_Count, - ByteSpan(reinterpret_cast(kSpake2pKeyExchangeSalt), strlen(kSpake2pKeyExchangeSalt)), 0, - &gExchangeMgr, &gTransports, &gSessions, fabricInfo)); + ByteSpan(reinterpret_cast(kSpake2pKeyExchangeSalt), strlen(kSpake2pKeyExchangeSalt)), 0, &gExchangeMgr, + &gTransports, &gSessions, fabricInfo)); if (commissioningTimeoutSeconds != kNoCommissioningTimeout) { diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index 8d77b8a17e5bef..edb4ff8187d223 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -368,7 +368,7 @@ CHIP_ERROR Device::OpenPairingWindow(uint16_t timeout, PairingWindowOption optio { bool randomSetupPIN = (option == PairingWindowOption::kTokenWithRandomPIN); PASEVerifier verifier; - ByteSpan salt(reinterpret_cast(kSpake2pKeyExchangeSalt), strlen(kSpake2pKeyExchangeSalt)); + ByteSpan salt(reinterpret_cast(kSpake2pKeyExchangeSalt), strlen(kSpake2pKeyExchangeSalt)); ReturnErrorOnFailure( PASESession::GeneratePASEVerifier(verifier, kSpake2p_Iteration_Count, salt, randomSetupPIN, setupPayload.setUpPINCode)); From 0ed62e311cc8b5719c76ac6dd614d02b848dcf9a Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Fri, 30 Jul 2021 10:16:36 -0700 Subject: [PATCH 05/10] address review comments --- .../administrator-commissioning-server.cpp | 19 ++++++++++++++++++- src/controller/CHIPDevice.cpp | 4 ++-- src/protocols/secure_channel/PASESession.h | 6 ++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp index 6ba164c83227b0..64b684712e4433 100644 --- a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp +++ b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp @@ -23,11 +23,15 @@ #include #include #include +#include #include #include using namespace chip; +// Specifications section 5.4.2.3. Announcement Duration +constexpr uint32_t kMaxCommissionioningTimeoutSeconds = 15 * 60; + bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(chip::EndpointId endpoint, app::CommandHandler * commandObj, uint16_t commissioningTimeout, ByteSpan pakeVerifier, @@ -36,10 +40,22 @@ bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(chi { EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; PASEVerifier verifier; + const uint8_t * verifierData = pakeVerifier.data(); + ChipLogProgress(Zcl, "Received command to open commissioning window"); + VerifyOrExit(!IsPairingWindowOpen(), status = EMBER_ZCL_STATUS_FAILURE); VerifyOrExit(sizeof(verifier) == pakeVerifier.size(), status = EMBER_ZCL_STATUS_FAILURE); - memcpy(&verifier[0][0], pakeVerifier.data(), pakeVerifier.size()); + VerifyOrExit(iterations >= kPBKDFMinimumIterations, status = EMBER_ZCL_STATUS_FAILURE); + VerifyOrExit(iterations <= kPBKDFMaximumIterations, status = EMBER_ZCL_STATUS_FAILURE); + VerifyOrExit(salt.size() >= kPBKDFMinimumSaltLen, status = EMBER_ZCL_STATUS_FAILURE); + VerifyOrExit(salt.size() <= kPBKDFMaximumSaltLen, status = EMBER_ZCL_STATUS_FAILURE); + VerifyOrExit(commissioningTimeout <= kMaxCommissionioningTimeoutSeconds, status = EMBER_ZCL_STATUS_FAILURE); + VerifyOrExit(discriminator <= kMaxDiscriminatorValue, status = EMBER_ZCL_STATUS_FAILURE); + + memcpy(&verifier[0][0], &verifierData[0], kSpake2p_WS_Length); + memcpy(&verifier[1][0], &verifierData[kSpake2p_WS_Length], kSpake2p_WS_Length); + VerifyOrExit(OpenPairingWindowUsingVerifier(commissioningTimeout, discriminator, verifier, iterations, salt, passcodeID) == CHIP_NO_ERROR, status = EMBER_ZCL_STATUS_FAILURE); @@ -61,6 +77,7 @@ bool emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallbac EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; ChipLogProgress(Zcl, "Received command to open basic commissioning window"); VerifyOrExit(!IsPairingWindowOpen(), status = EMBER_ZCL_STATUS_FAILURE); + VerifyOrExit(commissioningTimeout <= kMaxCommissionioningTimeoutSeconds, status = EMBER_ZCL_STATUS_FAILURE); VerifyOrExit(OpenDefaultPairingWindow(ResetFabrics::kNo, commissioningTimeout) == CHIP_NO_ERROR, status = EMBER_ZCL_STATUS_FAILURE); ChipLogProgress(Zcl, "Commissioning window is now open"); diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index edb4ff8187d223..a4b6f0c0e0e28a 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -370,11 +370,11 @@ CHIP_ERROR Device::OpenPairingWindow(uint16_t timeout, PairingWindowOption optio PASEVerifier verifier; ByteSpan salt(reinterpret_cast(kSpake2pKeyExchangeSalt), strlen(kSpake2pKeyExchangeSalt)); ReturnErrorOnFailure( - PASESession::GeneratePASEVerifier(verifier, kSpake2p_Iteration_Count, salt, randomSetupPIN, setupPayload.setUpPINCode)); + PASESession::GeneratePASEVerifier(verifier, kPBKDFMinimumIterations, salt, randomSetupPIN, setupPayload.setUpPINCode)); ReturnErrorOnFailure( cluster.OpenCommissioningWindow(successCallback, failureCallback, timeout, ByteSpan(&verifier[0][0], sizeof(verifier)), - setupPayload.discriminator, kSpake2p_Iteration_Count, salt, mPAKEVerifierID++)); + setupPayload.discriminator, kPBKDFMinimumIterations, salt, mPAKEVerifierID++)); } else { diff --git a/src/protocols/secure_channel/PASESession.h b/src/protocols/secure_channel/PASESession.h index 4cdfa798860603..08eecc75dde08b 100644 --- a/src/protocols/secure_channel/PASESession.h +++ b/src/protocols/secure_channel/PASESession.h @@ -53,6 +53,12 @@ extern const char * kSpake2pKeyExchangeSalt; constexpr uint16_t kPBKDFParamRandomNumberSize = 32; constexpr uint32_t kSpake2p_Iteration_Count = 100; +// Specifications section 3.9. Password-Based Key Derivation Function +constexpr uint32_t kPBKDFMinimumIterations = 1000; +constexpr uint32_t kPBKDFMaximumIterations = 100000; +constexpr uint32_t kPBKDFMinimumSaltLen = 16; +constexpr uint32_t kPBKDFMaximumSaltLen = 32; + using namespace Crypto; constexpr size_t kSpake2p_WS_Length = kP256_FE_Length + 8; From 8180a197483515d6dd450db20f11fd0d4c1e08ec Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Fri, 30 Jul 2021 14:38:18 -0700 Subject: [PATCH 06/10] update lock app build file --- examples/lock-app/esp32/main/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/lock-app/esp32/main/CMakeLists.txt b/examples/lock-app/esp32/main/CMakeLists.txt index 9e82d40343d48c..6be6b85e43d04d 100644 --- a/examples/lock-app/esp32/main/CMakeLists.txt +++ b/examples/lock-app/esp32/main/CMakeLists.txt @@ -125,6 +125,7 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" From 372a35eff110245029375474d3389906e5e20eb9 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 2 Aug 2021 08:12:33 -0700 Subject: [PATCH 07/10] fix Darwin build --- src/darwin/Framework/CHIP/CHIPDevice.mm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/darwin/Framework/CHIP/CHIPDevice.mm b/src/darwin/Framework/CHIP/CHIPDevice.mm index d44a514da81415..0d1d36140e5d72 100644 --- a/src/darwin/Framework/CHIP/CHIPDevice.mm +++ b/src/darwin/Framework/CHIP/CHIPDevice.mm @@ -57,8 +57,8 @@ - (BOOL)openPairingWindow:(NSUInteger)duration error:(NSError * __autoreleasing chip::SetupPayload setupPayload; - if (duration > UINT32_MAX) { - CHIP_LOG_ERROR("Error: Duration %tu is too large. Max value %d", duration, UINT32_MAX); + if (duration > UINT16_MAX) { + CHIP_LOG_ERROR("Error: Duration %tu is too large. Max value %d", duration, UINT16_MAX); if (error) { *error = [CHIPError errorForCHIPErrorCode:CHIP_ERROR_INVALID_INTEGER_VALUE]; } @@ -67,7 +67,7 @@ - (BOOL)openPairingWindow:(NSUInteger)duration error:(NSError * __autoreleasing [self.lock lock]; err = self.cppDevice->OpenPairingWindow( - (uint32_t) duration, chip::Controller::Device::PairingWindowOption::kOriginalSetupCode, setupPayload); + (uint16_t) duration, chip::Controller::Device::PairingWindowOption::kOriginalSetupCode, setupPayload); [self.lock unlock]; if (err != CHIP_NO_ERROR) { @@ -90,8 +90,8 @@ - (NSString *)openPairingWindowWithPIN:(NSUInteger)duration chip::SetupPayload setupPayload; - if (duration > UINT32_MAX) { - CHIP_LOG_ERROR("Error: Duration %tu is too large. Max value %d", duration, UINT32_MAX); + if (duration > UINT16_MAX) { + CHIP_LOG_ERROR("Error: Duration %tu is too large. Max value %d", duration, UINT16_MAX); if (error) { *error = [CHIPError errorForCHIPErrorCode:CHIP_ERROR_INVALID_INTEGER_VALUE]; } @@ -113,7 +113,7 @@ - (NSString *)openPairingWindowWithPIN:(NSUInteger)duration [self.lock lock]; err = self.cppDevice->OpenPairingWindow( - (uint32_t) duration, chip::Controller::Device::PairingWindowOption::kTokenWithProvidedPIN, setupPayload); + (uint16_t) duration, chip::Controller::Device::PairingWindowOption::kTokenWithProvidedPIN, setupPayload); [self.lock unlock]; if (err != CHIP_NO_ERROR) { From 1c79ba1e1f37f1a837c4a6ce3f81ad3962221bf5 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Mon, 2 Aug 2021 17:12:07 -0700 Subject: [PATCH 08/10] Fix Darwin test failures --- src/darwin/Framework/CHIP/templates/helper.js | 1 + src/darwin/Framework/CHIPTests/CHIPClustersTests.m | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/darwin/Framework/CHIP/templates/helper.js b/src/darwin/Framework/CHIP/templates/helper.js index 86f540f185a36f..2b08b1dfd9e28d 100644 --- a/src/darwin/Framework/CHIP/templates/helper.js +++ b/src/darwin/Framework/CHIP/templates/helper.js @@ -28,6 +28,7 @@ const StringHelper = require('../../../../../src/app/zap-templates/common/Str function asExpectedEndpointForCluster(clusterName) { switch (clusterName) { + case 'AdministratorCommissioning': case 'Basic': case 'Descriptor': case 'GeneralCommissioning': diff --git a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m index cb7082aacf21da..752db108b3c804 100644 --- a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m @@ -5284,7 +5284,7 @@ - (void)testSendClusterAdministratorCommissioningReadAttributeClusterRevisionWit CHIPDevice * device = GetPairedDevice(kDeviceId); dispatch_queue_t queue = dispatch_get_main_queue(); CHIPAdministratorCommissioning * cluster = [[CHIPAdministratorCommissioning alloc] initWithDevice:device - endpoint:1 + endpoint:0 queue:queue]; XCTAssertNotNil(cluster); From 26188576e270875532f985f136b33a537d8765ef Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 3 Aug 2021 11:07:11 -0700 Subject: [PATCH 09/10] address review comments --- .../administrator-commissioning-server.cpp | 4 ++-- src/controller/CHIPDevice.cpp | 10 ++++++---- src/protocols/secure_channel/PASESession.cpp | 14 +++++++------- src/protocols/secure_channel/PASESession.h | 6 +++++- .../secure_channel/RendezvousParameters.h | 2 +- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp index 64b684712e4433..86d7961c4e71ba 100644 --- a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp +++ b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp @@ -53,8 +53,8 @@ bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(chi VerifyOrExit(commissioningTimeout <= kMaxCommissionioningTimeoutSeconds, status = EMBER_ZCL_STATUS_FAILURE); VerifyOrExit(discriminator <= kMaxDiscriminatorValue, status = EMBER_ZCL_STATUS_FAILURE); - memcpy(&verifier[0][0], &verifierData[0], kSpake2p_WS_Length); - memcpy(&verifier[1][0], &verifierData[kSpake2p_WS_Length], kSpake2p_WS_Length); + memcpy(verifier.mW0, &verifierData[0], kSpake2p_WS_Length); + memcpy(verifier.mL, &verifierData[kSpake2p_WS_Length], kSpake2p_WS_Length); VerifyOrExit(OpenPairingWindowUsingVerifier(commissioningTimeout, discriminator, verifier, iterations, salt, passcodeID) == CHIP_NO_ERROR, diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index a4b6f0c0e0e28a..4f99d69fe8a9f2 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -358,8 +358,10 @@ void Device::OnOpenPairingWindowFailureResponse(void * context, uint8_t status) CHIP_ERROR Device::OpenPairingWindow(uint16_t timeout, PairingWindowOption option, SetupPayload & setupPayload) { + constexpr EndpointId kAdministratorCommissioningClusterEndpoint = 0; + chip::Controller::AdministratorCommissioningCluster cluster; - cluster.Associate(this, 0); + cluster.Associate(this, kAdministratorCommissioningClusterEndpoint); Callback::Cancelable * successCallback = mOpenPairingSuccessCallback.Cancel(); Callback::Cancelable * failureCallback = mOpenPairingFailureCallback.Cancel(); @@ -372,9 +374,9 @@ CHIP_ERROR Device::OpenPairingWindow(uint16_t timeout, PairingWindowOption optio ReturnErrorOnFailure( PASESession::GeneratePASEVerifier(verifier, kPBKDFMinimumIterations, salt, randomSetupPIN, setupPayload.setUpPINCode)); - ReturnErrorOnFailure( - cluster.OpenCommissioningWindow(successCallback, failureCallback, timeout, ByteSpan(&verifier[0][0], sizeof(verifier)), - setupPayload.discriminator, kPBKDFMinimumIterations, salt, mPAKEVerifierID++)); + ReturnErrorOnFailure(cluster.OpenCommissioningWindow( + successCallback, failureCallback, timeout, ByteSpan(reinterpret_cast(&verifier), sizeof(verifier)), + setupPayload.discriminator, kPBKDFMinimumIterations, salt, mPAKEVerifierID++)); } else { diff --git a/src/protocols/secure_channel/PASESession.cpp b/src/protocols/secure_channel/PASESession.cpp index a86b93b0efed7c..9a99ec44d368b3 100644 --- a/src/protocols/secure_channel/PASESession.cpp +++ b/src/protocols/secure_channel/PASESession.cpp @@ -80,7 +80,7 @@ void PASESession::Clear() // This function zeroes out and resets the memory used by the object. // It's done so that no security related information will be leaked. memset(&mPoint[0], 0, sizeof(mPoint)); - memset(&mPASEVerifier[0][0], 0, sizeof(mPASEVerifier)); + memset(&mPASEVerifier, 0, sizeof(mPASEVerifier)); memset(&mKe[0], 0, sizeof(mKe)); mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2pError; @@ -209,7 +209,7 @@ CHIP_ERROR PASESession::ComputePASEVerifier(uint32_t setUpPINCode, uint32_t pbkd Encoding::LittleEndian::Put32(littleEndianSetupPINCode, setUpPINCode); return mPBKDF.pbkdf2_sha256(littleEndianSetupPINCode, sizeof(littleEndianSetupPINCode), salt.data(), salt.size(), - pbkdf2IterCount, sizeof(PASEVerifier), &verifier[0][0]); + pbkdf2IterCount, sizeof(PASEVerifier), reinterpret_cast(&verifier)); } CHIP_ERROR PASESession::GeneratePASEVerifier(PASEVerifier & verifier, uint32_t pbkdf2IterCount, const ByteSpan & salt, @@ -292,7 +292,7 @@ CHIP_ERROR PASESession::WaitForPairing(const PASEVerifier & verifier, uint32_t p { ReturnErrorOnFailure(WaitForPairing(0, pbkdf2IterCount, salt, myKeyId, delegate)); - memmove(&mPASEVerifier, verifier, sizeof(verifier)); + memmove(&mPASEVerifier, &verifier, sizeof(verifier)); mComputeVerifier = false; mPasscodeID = passcodeID; @@ -427,7 +427,7 @@ CHIP_ERROR PASESession::SendPBKDFParamResponse() // Update commissioning hash with the pbkdf2 param response that's being sent. ReturnErrorOnFailure(mCommissioningHash.AddData(ByteSpan{ resp->Start(), resp->DataLength() })); ReturnErrorOnFailure(SetupSpake2p(mIterationCount, ByteSpan(mSalt, mSaltLength))); - ReturnErrorOnFailure(mSpake2p.ComputeL(mPoint, &sizeof_point, &mPASEVerifier[1][0], kSpake2p_WS_Length)); + ReturnErrorOnFailure(mSpake2p.ComputeL(mPoint, &sizeof_point, mPASEVerifier.mL, kSpake2p_WS_Length)); mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2p1; @@ -492,8 +492,8 @@ CHIP_ERROR PASESession::SendMsg1() uint8_t X[kMAX_Point_Length]; size_t X_len = sizeof(X); - ReturnErrorOnFailure(mSpake2p.BeginProver(nullptr, 0, nullptr, 0, &mPASEVerifier[0][0], kSpake2p_WS_Length, - &mPASEVerifier[1][0], kSpake2p_WS_Length)); + ReturnErrorOnFailure( + mSpake2p.BeginProver(nullptr, 0, nullptr, 0, mPASEVerifier.mW0, kSpake2p_WS_Length, mPASEVerifier.mL, kSpake2p_WS_Length)); ReturnErrorOnFailure(mSpake2p.ComputeRoundOne(NULL, 0, X, &X_len)); @@ -535,7 +535,7 @@ CHIP_ERROR PASESession::HandleMsg1_and_SendMsg2(const System::PacketBufferHandle VerifyOrExit(buf != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE); VerifyOrExit(buf_len == sizeof(encryptionKeyId) + kMAX_Point_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); - err = mSpake2p.BeginVerifier(nullptr, 0, nullptr, 0, &mPASEVerifier[0][0], kSpake2p_WS_Length, mPoint, sizeof(mPoint)); + err = mSpake2p.BeginVerifier(nullptr, 0, nullptr, 0, mPASEVerifier.mW0, kSpake2p_WS_Length, mPoint, sizeof(mPoint)); SuccessOrExit(err); encryptionKeyId = chip::Encoding::LittleEndian::Read16(buf); diff --git a/src/protocols/secure_channel/PASESession.h b/src/protocols/secure_channel/PASESession.h index 08eecc75dde08b..b9de64824b8205 100644 --- a/src/protocols/secure_channel/PASESession.h +++ b/src/protocols/secure_channel/PASESession.h @@ -74,7 +74,11 @@ struct PASESessionSerializable uint16_t mPeerKeyId; }; -typedef uint8_t PASEVerifier[2][kSpake2p_WS_Length]; +struct PASEVerifier +{ + uint8_t mW0[kSpake2p_WS_Length]; + uint8_t mL[kSpake2p_WS_Length]; +}; class DLL_EXPORT PASESession : public Messaging::ExchangeDelegate, public PairingSession { diff --git a/src/protocols/secure_channel/RendezvousParameters.h b/src/protocols/secure_channel/RendezvousParameters.h index fda1299c2be37c..0dab80e7515ea4 100644 --- a/src/protocols/secure_channel/RendezvousParameters.h +++ b/src/protocols/secure_channel/RendezvousParameters.h @@ -106,7 +106,7 @@ class RendezvousParameters const PASEVerifier & GetPASEVerifier() const { return mPASEVerifier; } RendezvousParameters & SetPASEVerifier(PASEVerifier & verifier) { - memmove(mPASEVerifier, verifier, sizeof(verifier)); + memmove(&mPASEVerifier, &verifier, sizeof(verifier)); mHasPASEVerifier = true; return *this; } From 3ab1a683ab59b2f934252b69e09488d6b4d94120 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Tue, 3 Aug 2021 14:59:42 -0700 Subject: [PATCH 10/10] Address review comments --- src/app/server/RendezvousServer.cpp | 13 +++++++------ src/app/server/Server.cpp | 10 ++-------- src/controller/CHIPDevice.cpp | 8 +++++++- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/app/server/RendezvousServer.cpp b/src/app/server/RendezvousServer.cpp index 58b6b52b01300a..42cb0113ad68e5 100644 --- a/src/app/server/RendezvousServer.cpp +++ b/src/app/server/RendezvousServer.cpp @@ -82,17 +82,18 @@ CHIP_ERROR RendezvousServer::WaitForPairing(const RendezvousParameters & params, mAdvDelegate = params.GetAdvertisementDelegate(); - // Note: Since BLE is only used for initial setup, enable BLE advertisement in rendezvous session can be expected. if (params.GetPeerAddress().GetTransportType() == Transport::Type::kBle) -#if CONFIG_NETWORK_LAYER_BLE - { - ReturnErrorOnFailure(GetAdvertisementDelegate()->StartAdvertisement()); - } -#else +#if !CONFIG_NETWORK_LAYER_BLE { return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; } #endif + + if (HasAdvertisementDelegate()) + { + ReturnErrorOnFailure(GetAdvertisementDelegate()->StartAdvertisement()); + } + mSessionMgr = sessionMgr; mFabric = fabric; mExchangeManager = exchangeManager; diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index fc47d58daea370..1436e3af9d7089 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -423,14 +423,8 @@ CHIP_ERROR OpenPairingWindowUsingVerifier(uint16_t commissioningTimeoutSeconds, ReturnErrorOnFailure(gDeviceDiscriminatorCache.UpdateDiscriminator(discriminator)); -#if CONFIG_NETWORK_LAYER_BLE - params.SetPASEVerifier(verifier) - .SetBleLayer(DeviceLayer::ConnectivityMgr().GetBleLayer()) - .SetPeerAddress(Transport::PeerAddress::BLE()) - .SetAdvertisementDelegate(&gAdvDelegate); -#else - params.SetPASEVerifier(verifier); -#endif // CONFIG_NETWORK_LAYER_BLE + gAdvDelegate.SetBLE(false); + params.SetPASEVerifier(verifier).SetAdvertisementDelegate(&gAdvDelegate); FabricIndex fabricIndex = gNextAvailableFabricIndex; FabricInfo * fabricInfo = gFabrics.AssignFabricIndex(fabricIndex); diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp index 4f99d69fe8a9f2..54487f94f88cd1 100644 --- a/src/controller/CHIPDevice.cpp +++ b/src/controller/CHIPDevice.cpp @@ -374,8 +374,14 @@ CHIP_ERROR Device::OpenPairingWindow(uint16_t timeout, PairingWindowOption optio ReturnErrorOnFailure( PASESession::GeneratePASEVerifier(verifier, kPBKDFMinimumIterations, salt, randomSetupPIN, setupPayload.setUpPINCode)); + uint8_t serializedVerifier[2 * kSpake2p_WS_Length]; + VerifyOrReturnError(sizeof(serializedVerifier) == sizeof(verifier), CHIP_ERROR_INTERNAL); + + memcpy(serializedVerifier, verifier.mW0, kSpake2p_WS_Length); + memcpy(&serializedVerifier[kSpake2p_WS_Length], verifier.mL, kSpake2p_WS_Length); + ReturnErrorOnFailure(cluster.OpenCommissioningWindow( - successCallback, failureCallback, timeout, ByteSpan(reinterpret_cast(&verifier), sizeof(verifier)), + successCallback, failureCallback, timeout, ByteSpan(serializedVerifier, sizeof(serializedVerifier)), setupPayload.discriminator, kPBKDFMinimumIterations, salt, mPAKEVerifierID++)); } else